mirror of
https://github.com/nginx/nginx.git
synced 2024-12-12 02:09:04 +08:00
Resolver: implemented IPv6 address to name resolving.
This commit is contained in:
parent
3aeefbcaea
commit
809bee30b7
@ -92,6 +92,13 @@ static ngx_addr_t *ngx_resolver_export(ngx_resolver_t *r, in_addr_t *src,
|
|||||||
ngx_uint_t n, ngx_uint_t rotate);
|
ngx_uint_t n, ngx_uint_t rotate);
|
||||||
static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len);
|
static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len);
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
static void ngx_resolver_rbtree_insert_addr6_value(ngx_rbtree_node_t *temp,
|
||||||
|
ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
|
||||||
|
static ngx_resolver_node_t *ngx_resolver_lookup_addr6(ngx_resolver_t *r,
|
||||||
|
struct in6_addr *addr, uint32_t hash);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
ngx_resolver_t *
|
ngx_resolver_t *
|
||||||
ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
|
ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
|
||||||
@ -134,6 +141,15 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
|
|||||||
ngx_queue_init(&r->name_expire_queue);
|
ngx_queue_init(&r->name_expire_queue);
|
||||||
ngx_queue_init(&r->addr_expire_queue);
|
ngx_queue_init(&r->addr_expire_queue);
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
ngx_rbtree_init(&r->addr6_rbtree, &r->addr6_sentinel,
|
||||||
|
ngx_resolver_rbtree_insert_addr6_value);
|
||||||
|
|
||||||
|
ngx_queue_init(&r->addr6_resend_queue);
|
||||||
|
|
||||||
|
ngx_queue_init(&r->addr6_expire_queue);
|
||||||
|
#endif
|
||||||
|
|
||||||
r->event->handler = ngx_resolver_resend_handler;
|
r->event->handler = ngx_resolver_resend_handler;
|
||||||
r->event->data = r;
|
r->event->data = r;
|
||||||
r->event->log = &cf->cycle->new_log;
|
r->event->log = &cf->cycle->new_log;
|
||||||
@ -220,6 +236,10 @@ ngx_resolver_cleanup(void *data)
|
|||||||
|
|
||||||
ngx_resolver_cleanup_tree(r, &r->addr_rbtree);
|
ngx_resolver_cleanup_tree(r, &r->addr_rbtree);
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
ngx_resolver_cleanup_tree(r, &r->addr6_rbtree);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (r->event) {
|
if (r->event) {
|
||||||
ngx_free(r->event);
|
ngx_free(r->event);
|
||||||
}
|
}
|
||||||
@ -640,23 +660,50 @@ failed:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* AF_INET only */
|
|
||||||
|
|
||||||
ngx_int_t
|
ngx_int_t
|
||||||
ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
|
ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
u_char *name;
|
u_char *name;
|
||||||
in_addr_t addr;
|
in_addr_t addr;
|
||||||
|
ngx_queue_t *resend_queue, *expire_queue;
|
||||||
|
ngx_rbtree_t *tree;
|
||||||
ngx_resolver_t *r;
|
ngx_resolver_t *r;
|
||||||
struct sockaddr_in *sin;
|
struct sockaddr_in *sin;
|
||||||
ngx_resolver_node_t *rn;
|
ngx_resolver_node_t *rn;
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
uint32_t hash;
|
||||||
|
struct sockaddr_in6 *sin6;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NGX_SUPPRESS_WARN)
|
||||||
|
addr = 0;
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
hash = 0;
|
||||||
|
sin6 = NULL;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
r = ctx->resolver;
|
r = ctx->resolver;
|
||||||
|
|
||||||
if (ctx->addr.sockaddr->sa_family != AF_INET) {
|
switch (ctx->addr.sockaddr->sa_family) {
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
case AF_INET6:
|
||||||
|
sin6 = (struct sockaddr_in6 *) ctx->addr.sockaddr;
|
||||||
|
hash = ngx_crc32_short(sin6->sin6_addr.s6_addr, 16);
|
||||||
|
|
||||||
|
/* lock addr mutex */
|
||||||
|
|
||||||
|
rn = ngx_resolver_lookup_addr6(r, &sin6->sin6_addr, hash);
|
||||||
|
|
||||||
|
tree = &r->addr6_rbtree;
|
||||||
|
resend_queue = &r->addr6_resend_queue;
|
||||||
|
expire_queue = &r->addr6_expire_queue;
|
||||||
|
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default: /* AF_INET */
|
||||||
sin = (struct sockaddr_in *) ctx->addr.sockaddr;
|
sin = (struct sockaddr_in *) ctx->addr.sockaddr;
|
||||||
addr = ntohl(sin->sin_addr.s_addr);
|
addr = ntohl(sin->sin_addr.s_addr);
|
||||||
|
|
||||||
@ -664,6 +711,11 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
|
|||||||
|
|
||||||
rn = ngx_resolver_lookup_addr(r, addr);
|
rn = ngx_resolver_lookup_addr(r, addr);
|
||||||
|
|
||||||
|
tree = &r->addr_rbtree;
|
||||||
|
resend_queue = &r->addr_resend_queue;
|
||||||
|
expire_queue = &r->addr_expire_queue;
|
||||||
|
}
|
||||||
|
|
||||||
if (rn) {
|
if (rn) {
|
||||||
|
|
||||||
if (rn->valid >= ngx_time()) {
|
if (rn->valid >= ngx_time()) {
|
||||||
@ -674,7 +726,7 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
|
|||||||
|
|
||||||
rn->expire = ngx_time() + r->expire;
|
rn->expire = ngx_time() + r->expire;
|
||||||
|
|
||||||
ngx_queue_insert_head(&r->addr_expire_queue, &rn->queue);
|
ngx_queue_insert_head(expire_queue, &rn->queue);
|
||||||
|
|
||||||
name = ngx_resolver_dup(r, rn->name, rn->nlen);
|
name = ngx_resolver_dup(r, rn->name, rn->nlen);
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
@ -717,10 +769,22 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
|
|||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (ctx->addr.sockaddr->sa_family) {
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
case AF_INET6:
|
||||||
|
rn->addr6 = sin6->sin6_addr;
|
||||||
|
rn->node.key = hash;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default: /* AF_INET */
|
||||||
rn->node.key = addr;
|
rn->node.key = addr;
|
||||||
|
}
|
||||||
|
|
||||||
rn->query = NULL;
|
rn->query = NULL;
|
||||||
|
|
||||||
ngx_rbtree_insert(&r->addr_rbtree, &rn->node);
|
ngx_rbtree_insert(tree, &rn->node);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ngx_resolver_create_addr_query(rn, ctx) != NGX_OK) {
|
if (ngx_resolver_create_addr_query(rn, ctx) != NGX_OK) {
|
||||||
@ -743,13 +807,13 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
|
|||||||
|
|
||||||
ngx_add_timer(ctx->event, ctx->timeout);
|
ngx_add_timer(ctx->event, ctx->timeout);
|
||||||
|
|
||||||
if (ngx_queue_empty(&r->addr_resend_queue)) {
|
if (ngx_queue_empty(resend_queue)) {
|
||||||
ngx_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000));
|
ngx_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000));
|
||||||
}
|
}
|
||||||
|
|
||||||
rn->expire = ngx_time() + r->resend_timeout;
|
rn->expire = ngx_time() + r->resend_timeout;
|
||||||
|
|
||||||
ngx_queue_insert_head(&r->addr_resend_queue, &rn->queue);
|
ngx_queue_insert_head(resend_queue, &rn->queue);
|
||||||
|
|
||||||
rn->cnlen = 0;
|
rn->cnlen = 0;
|
||||||
rn->naddrs = 0;
|
rn->naddrs = 0;
|
||||||
@ -767,7 +831,7 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
|
|||||||
failed:
|
failed:
|
||||||
|
|
||||||
if (rn) {
|
if (rn) {
|
||||||
ngx_rbtree_delete(&r->addr_rbtree, &rn->node);
|
ngx_rbtree_delete(tree, &rn->node);
|
||||||
|
|
||||||
if (rn->query) {
|
if (rn->query) {
|
||||||
ngx_resolver_free(r, rn->query);
|
ngx_resolver_free(r, rn->query);
|
||||||
@ -788,26 +852,37 @@ failed:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* AF_INET only */
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx)
|
ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
in_addr_t addr;
|
in_addr_t addr;
|
||||||
|
ngx_queue_t *expire_queue;
|
||||||
|
ngx_rbtree_t *tree;
|
||||||
ngx_resolver_t *r;
|
ngx_resolver_t *r;
|
||||||
ngx_resolver_ctx_t *w, **p;
|
ngx_resolver_ctx_t *w, **p;
|
||||||
struct sockaddr_in *sin;
|
struct sockaddr_in *sin;
|
||||||
ngx_resolver_node_t *rn;
|
ngx_resolver_node_t *rn;
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
if (ctx->addr.sockaddr->sa_family != AF_INET) {
|
uint32_t hash;
|
||||||
return;
|
struct sockaddr_in6 *sin6;
|
||||||
}
|
#endif
|
||||||
|
|
||||||
sin = (struct sockaddr_in *) ctx->addr.sockaddr;
|
|
||||||
addr = ntohl(sin->sin_addr.s_addr);
|
|
||||||
|
|
||||||
r = ctx->resolver;
|
r = ctx->resolver;
|
||||||
|
|
||||||
|
switch (ctx->addr.sockaddr->sa_family) {
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
case AF_INET6:
|
||||||
|
tree = &r->addr6_rbtree;
|
||||||
|
expire_queue = &r->addr6_expire_queue;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default: /* AF_INET */
|
||||||
|
tree = &r->addr_rbtree;
|
||||||
|
expire_queue = &r->addr_expire_queue;
|
||||||
|
}
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
|
||||||
"resolve addr done: %i", ctx->state);
|
"resolve addr done: %i", ctx->state);
|
||||||
|
|
||||||
@ -819,7 +894,21 @@ ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx)
|
|||||||
|
|
||||||
if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) {
|
if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) {
|
||||||
|
|
||||||
|
switch (ctx->addr.sockaddr->sa_family) {
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
case AF_INET6:
|
||||||
|
sin6 = (struct sockaddr_in6 *) ctx->addr.sockaddr;
|
||||||
|
hash = ngx_crc32_short(sin6->sin6_addr.s6_addr, 16);
|
||||||
|
rn = ngx_resolver_lookup_addr6(r, &sin6->sin6_addr, hash);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default: /* AF_INET */
|
||||||
|
sin = (struct sockaddr_in *) ctx->addr.sockaddr;
|
||||||
|
addr = ntohl(sin->sin_addr.s_addr);
|
||||||
rn = ngx_resolver_lookup_addr(r, addr);
|
rn = ngx_resolver_lookup_addr(r, addr);
|
||||||
|
}
|
||||||
|
|
||||||
if (rn) {
|
if (rn) {
|
||||||
p = &rn->waiting;
|
p = &rn->waiting;
|
||||||
@ -837,15 +926,22 @@ ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
u_char text[NGX_SOCKADDR_STRLEN];
|
||||||
|
ngx_str_t addrtext;
|
||||||
|
|
||||||
|
addrtext.data = text;
|
||||||
|
addrtext.len = ngx_sock_ntop(ctx->addr.sockaddr, ctx->addr.socklen,
|
||||||
|
text, NGX_SOCKADDR_STRLEN, 0);
|
||||||
|
|
||||||
ngx_log_error(NGX_LOG_ALERT, r->log, 0,
|
ngx_log_error(NGX_LOG_ALERT, r->log, 0,
|
||||||
"could not cancel %ud.%ud.%ud.%ud resolving",
|
"could not cancel %V resolving", &addrtext);
|
||||||
(addr >> 24) & 0xff, (addr >> 16) & 0xff,
|
}
|
||||||
(addr >> 8) & 0xff, addr & 0xff);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
||||||
ngx_resolver_expire(r, &r->addr_rbtree, &r->addr_expire_queue);
|
ngx_resolver_expire(r, tree, expire_queue);
|
||||||
|
|
||||||
/* unlock addr mutex */
|
/* unlock addr mutex */
|
||||||
|
|
||||||
@ -946,6 +1042,9 @@ static void
|
|||||||
ngx_resolver_resend_handler(ngx_event_t *ev)
|
ngx_resolver_resend_handler(ngx_event_t *ev)
|
||||||
{
|
{
|
||||||
time_t timer, atimer, ntimer;
|
time_t timer, atimer, ntimer;
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
time_t a6timer;
|
||||||
|
#endif
|
||||||
ngx_resolver_t *r;
|
ngx_resolver_t *r;
|
||||||
|
|
||||||
r = ev->data;
|
r = ev->data;
|
||||||
@ -965,16 +1064,36 @@ ngx_resolver_resend_handler(ngx_event_t *ev)
|
|||||||
|
|
||||||
/* unlock addr mutex */
|
/* unlock addr mutex */
|
||||||
|
|
||||||
if (ntimer == 0) {
|
#if (NGX_HAVE_INET6)
|
||||||
timer = atimer;
|
|
||||||
|
/* lock addr6 mutex */
|
||||||
|
|
||||||
|
a6timer = ngx_resolver_resend(r, &r->addr6_rbtree, &r->addr6_resend_queue);
|
||||||
|
|
||||||
|
/* unlock addr6 mutex */
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
} else if (atimer == 0) {
|
|
||||||
timer = ntimer;
|
timer = ntimer;
|
||||||
|
|
||||||
} else {
|
if (timer == 0) {
|
||||||
timer = (atimer < ntimer) ? atimer : ntimer;
|
timer = atimer;
|
||||||
|
|
||||||
|
} else if (atimer) {
|
||||||
|
timer = ngx_min(timer, atimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
|
||||||
|
if (timer == 0) {
|
||||||
|
timer = a6timer;
|
||||||
|
|
||||||
|
} else if (a6timer) {
|
||||||
|
timer = ngx_min(timer, a6timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
if (timer) {
|
if (timer) {
|
||||||
ngx_add_timer(r->event, (ngx_msec_t) (timer * 1000));
|
ngx_add_timer(r->event, (ngx_msec_t) (timer * 1000));
|
||||||
}
|
}
|
||||||
@ -1555,14 +1674,22 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
|
|||||||
{
|
{
|
||||||
char *err;
|
char *err;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
u_char text[NGX_SOCKADDR_STRLEN];
|
||||||
in_addr_t addr;
|
in_addr_t addr;
|
||||||
int32_t ttl;
|
int32_t ttl;
|
||||||
ngx_int_t octet;
|
ngx_int_t octet;
|
||||||
ngx_str_t name;
|
ngx_str_t name;
|
||||||
ngx_uint_t i, mask, qident, class;
|
ngx_uint_t i, mask, qident, class;
|
||||||
|
ngx_queue_t *expire_queue;
|
||||||
|
ngx_rbtree_t *tree;
|
||||||
ngx_resolver_an_t *an;
|
ngx_resolver_an_t *an;
|
||||||
ngx_resolver_ctx_t *ctx, *next;
|
ngx_resolver_ctx_t *ctx, *next;
|
||||||
ngx_resolver_node_t *rn;
|
ngx_resolver_node_t *rn;
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
uint32_t hash;
|
||||||
|
ngx_int_t digit;
|
||||||
|
struct in6_addr addr6;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (ngx_resolver_copy(r, NULL, buf,
|
if (ngx_resolver_copy(r, NULL, buf,
|
||||||
buf + sizeof(ngx_resolver_hdr_t), buf + n)
|
buf + sizeof(ngx_resolver_hdr_t), buf + n)
|
||||||
@ -1571,6 +1698,8 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* AF_INET */
|
||||||
|
|
||||||
addr = 0;
|
addr = 0;
|
||||||
i = sizeof(ngx_resolver_hdr_t);
|
i = sizeof(ngx_resolver_hdr_t);
|
||||||
|
|
||||||
@ -1586,19 +1715,82 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
|
|||||||
i += len;
|
i += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ngx_strcmp(&buf[i], "\7in-addr\4arpa") != 0) {
|
if (ngx_strcmp(&buf[i], "\7in-addr\4arpa") == 0) {
|
||||||
goto invalid_in_addr_arpa;
|
i += sizeof("\7in-addr\4arpa");
|
||||||
}
|
|
||||||
|
|
||||||
/* lock addr mutex */
|
/* lock addr mutex */
|
||||||
|
|
||||||
rn = ngx_resolver_lookup_addr(r, addr);
|
rn = ngx_resolver_lookup_addr(r, addr);
|
||||||
|
|
||||||
|
tree = &r->addr_rbtree;
|
||||||
|
expire_queue = &r->addr_expire_queue;
|
||||||
|
|
||||||
|
addr = htonl(addr);
|
||||||
|
name.len = ngx_inet_ntop(AF_INET, &addr, text, NGX_SOCKADDR_STRLEN);
|
||||||
|
name.data = text;
|
||||||
|
|
||||||
|
goto valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
invalid_in_addr_arpa:
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
|
||||||
|
i = sizeof(ngx_resolver_hdr_t);
|
||||||
|
|
||||||
|
for (octet = 15; octet >= 0; octet--) {
|
||||||
|
if (buf[i++] != '\1') {
|
||||||
|
goto invalid_ip6_arpa;
|
||||||
|
}
|
||||||
|
|
||||||
|
digit = ngx_hextoi(&buf[i++], 1);
|
||||||
|
if (digit == NGX_ERROR) {
|
||||||
|
goto invalid_ip6_arpa;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr6.s6_addr[octet] = (u_char) digit;
|
||||||
|
|
||||||
|
if (buf[i++] != '\1') {
|
||||||
|
goto invalid_ip6_arpa;
|
||||||
|
}
|
||||||
|
|
||||||
|
digit = ngx_hextoi(&buf[i++], 1);
|
||||||
|
if (digit == NGX_ERROR) {
|
||||||
|
goto invalid_ip6_arpa;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr6.s6_addr[octet] += (u_char) (digit * 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_strcmp(&buf[i], "\3ip6\4arpa") == 0) {
|
||||||
|
i += sizeof("\3ip6\4arpa");
|
||||||
|
|
||||||
|
/* lock addr mutex */
|
||||||
|
|
||||||
|
hash = ngx_crc32_short(addr6.s6_addr, 16);
|
||||||
|
rn = ngx_resolver_lookup_addr6(r, &addr6, hash);
|
||||||
|
|
||||||
|
tree = &r->addr6_rbtree;
|
||||||
|
expire_queue = &r->addr6_expire_queue;
|
||||||
|
|
||||||
|
name.len = ngx_inet6_ntop(addr6.s6_addr, text, NGX_SOCKADDR_STRLEN);
|
||||||
|
name.data = text;
|
||||||
|
|
||||||
|
goto valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
invalid_ip6_arpa:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ngx_log_error(r->log_level, r->log, 0,
|
||||||
|
"invalid in-addr.arpa or ip6.arpa name in DNS response");
|
||||||
|
return;
|
||||||
|
|
||||||
|
valid:
|
||||||
|
|
||||||
if (rn == NULL || rn->query == NULL) {
|
if (rn == NULL || rn->query == NULL) {
|
||||||
ngx_log_error(r->log_level, r->log, 0,
|
ngx_log_error(r->log_level, r->log, 0,
|
||||||
"unexpected response for %ud.%ud.%ud.%ud",
|
"unexpected response for %V", &name);
|
||||||
(addr >> 24) & 0xff, (addr >> 16) & 0xff,
|
|
||||||
(addr >> 8) & 0xff, addr & 0xff);
|
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1606,9 +1798,8 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
|
|||||||
|
|
||||||
if (ident != qident) {
|
if (ident != qident) {
|
||||||
ngx_log_error(r->log_level, r->log, 0,
|
ngx_log_error(r->log_level, r->log, 0,
|
||||||
"wrong ident %ui response for %ud.%ud.%ud.%ud, expect %ui",
|
"wrong ident %ui response for %V, expect %ui",
|
||||||
ident, (addr >> 24) & 0xff, (addr >> 16) & 0xff,
|
ident, &name, qident);
|
||||||
(addr >> 8) & 0xff, addr & 0xff, qident);
|
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1622,7 +1813,7 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
|
|||||||
|
|
||||||
ngx_queue_remove(&rn->queue);
|
ngx_queue_remove(&rn->queue);
|
||||||
|
|
||||||
ngx_rbtree_delete(&r->addr_rbtree, &rn->node);
|
ngx_rbtree_delete(tree, &rn->node);
|
||||||
|
|
||||||
ngx_resolver_free_node(r, rn);
|
ngx_resolver_free_node(r, rn);
|
||||||
|
|
||||||
@ -1639,16 +1830,16 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
i += sizeof("\7in-addr\4arpa") + sizeof(ngx_resolver_qs_t);
|
i += sizeof(ngx_resolver_qs_t);
|
||||||
|
|
||||||
if (i + 2 + sizeof(ngx_resolver_an_t) >= n) {
|
if (i + 2 + sizeof(ngx_resolver_an_t) >= n) {
|
||||||
goto short_response;
|
goto short_response;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* compression pointer to "XX.XX.XX.XX.in-addr.arpa */
|
/* compression pointer to *.arpa */
|
||||||
|
|
||||||
if (buf[i] != 0xc0 || buf[i + 1] != sizeof(ngx_resolver_hdr_t)) {
|
if (buf[i] != 0xc0 || buf[i + 1] != sizeof(ngx_resolver_hdr_t)) {
|
||||||
err = "invalid in-addr.arpa name in DNS response";
|
err = "invalid in-addr.arpa or ip6.arpa name in DNS response";
|
||||||
goto invalid;
|
goto invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1707,7 +1898,7 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
|
|||||||
rn->valid = ngx_time() + (r->valid ? r->valid : ttl);
|
rn->valid = ngx_time() + (r->valid ? r->valid : ttl);
|
||||||
rn->expire = ngx_time() + r->expire;
|
rn->expire = ngx_time() + r->expire;
|
||||||
|
|
||||||
ngx_queue_insert_head(&r->addr_expire_queue, &rn->queue);
|
ngx_queue_insert_head(expire_queue, &rn->queue);
|
||||||
|
|
||||||
next = rn->waiting;
|
next = rn->waiting;
|
||||||
rn->waiting = NULL;
|
rn->waiting = NULL;
|
||||||
@ -1727,12 +1918,6 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
|
|||||||
|
|
||||||
return;
|
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:
|
short_response:
|
||||||
|
|
||||||
err = "short DNS response";
|
err = "short DNS response";
|
||||||
@ -1825,6 +2010,52 @@ ngx_resolver_lookup_addr(ngx_resolver_t *r, in_addr_t addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
|
||||||
|
static ngx_resolver_node_t *
|
||||||
|
ngx_resolver_lookup_addr6(ngx_resolver_t *r, struct in6_addr *addr,
|
||||||
|
uint32_t hash)
|
||||||
|
{
|
||||||
|
ngx_int_t rc;
|
||||||
|
ngx_rbtree_node_t *node, *sentinel;
|
||||||
|
ngx_resolver_node_t *rn;
|
||||||
|
|
||||||
|
node = r->addr6_rbtree.root;
|
||||||
|
sentinel = r->addr6_rbtree.sentinel;
|
||||||
|
|
||||||
|
while (node != sentinel) {
|
||||||
|
|
||||||
|
if (hash < node->key) {
|
||||||
|
node = node->left;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hash > node->key) {
|
||||||
|
node = node->right;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* hash == node->key */
|
||||||
|
|
||||||
|
rn = (ngx_resolver_node_t *) node;
|
||||||
|
|
||||||
|
rc = ngx_memcmp(addr, &rn->addr6, 16);
|
||||||
|
|
||||||
|
if (rc == 0) {
|
||||||
|
return rn;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = (rc < 0) ? node->left : node->right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not found */
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp,
|
ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp,
|
||||||
ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
|
ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
|
||||||
@ -1866,6 +2097,51 @@ ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
|
||||||
|
static void
|
||||||
|
ngx_resolver_rbtree_insert_addr6_value(ngx_rbtree_node_t *temp,
|
||||||
|
ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
|
||||||
|
{
|
||||||
|
ngx_rbtree_node_t **p;
|
||||||
|
ngx_resolver_node_t *rn, *rn_temp;
|
||||||
|
|
||||||
|
for ( ;; ) {
|
||||||
|
|
||||||
|
if (node->key < temp->key) {
|
||||||
|
|
||||||
|
p = &temp->left;
|
||||||
|
|
||||||
|
} else if (node->key > temp->key) {
|
||||||
|
|
||||||
|
p = &temp->right;
|
||||||
|
|
||||||
|
} else { /* node->key == temp->key */
|
||||||
|
|
||||||
|
rn = (ngx_resolver_node_t *) node;
|
||||||
|
rn_temp = (ngx_resolver_node_t *) temp;
|
||||||
|
|
||||||
|
p = (ngx_memcmp(&rn->addr6, &rn_temp->addr6, 16)
|
||||||
|
< 0) ? &temp->left : &temp->right;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p == sentinel) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
temp = *p;
|
||||||
|
}
|
||||||
|
|
||||||
|
*p = node;
|
||||||
|
node->parent = temp;
|
||||||
|
node->left = sentinel;
|
||||||
|
node->right = sentinel;
|
||||||
|
ngx_rbt_red(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
|
ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
@ -1953,8 +2229,6 @@ ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* AF_INET only */
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
|
ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
@ -1965,14 +2239,26 @@ ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
|
|||||||
ngx_uint_t ident;
|
ngx_uint_t ident;
|
||||||
ngx_resolver_hdr_t *query;
|
ngx_resolver_hdr_t *query;
|
||||||
struct sockaddr_in *sin;
|
struct sockaddr_in *sin;
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
struct sockaddr_in6 *sin6;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (ctx->addr.sockaddr->sa_family != AF_INET) {
|
switch (ctx->addr.sockaddr->sa_family) {
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
case AF_INET6:
|
||||||
|
len = sizeof(ngx_resolver_hdr_t)
|
||||||
|
+ 64 + sizeof(".ip6.arpa.") - 1
|
||||||
|
+ sizeof(ngx_resolver_qs_t);
|
||||||
|
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default: /* AF_INET */
|
||||||
len = sizeof(ngx_resolver_hdr_t)
|
len = sizeof(ngx_resolver_hdr_t)
|
||||||
+ sizeof(".255.255.255.255.in-addr.arpa.") - 1
|
+ sizeof(".255.255.255.255.in-addr.arpa.") - 1
|
||||||
+ sizeof(ngx_resolver_qs_t);
|
+ sizeof(ngx_resolver_qs_t);
|
||||||
|
}
|
||||||
|
|
||||||
p = ngx_resolver_alloc(ctx->resolver, len);
|
p = ngx_resolver_alloc(ctx->resolver, len);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
@ -1998,6 +2284,25 @@ ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
|
|||||||
|
|
||||||
p += sizeof(ngx_resolver_hdr_t);
|
p += sizeof(ngx_resolver_hdr_t);
|
||||||
|
|
||||||
|
switch (ctx->addr.sockaddr->sa_family) {
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
case AF_INET6:
|
||||||
|
sin6 = (struct sockaddr_in6 *) ctx->addr.sockaddr;
|
||||||
|
|
||||||
|
for (n = 15; n >= 0; n--) {
|
||||||
|
p = ngx_sprintf(p, "\1%xd\1%xd",
|
||||||
|
sin6->sin6_addr.s6_addr[n] & 0xf,
|
||||||
|
(sin6->sin6_addr.s6_addr[n] >> 4) & 0xf);
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ngx_cpymem(p, "\3ip6\4arpa\0", 10);
|
||||||
|
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default: /* AF_INET */
|
||||||
|
|
||||||
sin = (struct sockaddr_in *) ctx->addr.sockaddr;
|
sin = (struct sockaddr_in *) ctx->addr.sockaddr;
|
||||||
addr = ntohl(sin->sin_addr.s_addr);
|
addr = ntohl(sin->sin_addr.s_addr);
|
||||||
|
|
||||||
@ -2007,12 +2312,13 @@ ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
|
|||||||
p = d;
|
p = d;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* query type "PTR", IN query class */
|
p = ngx_cpymem(p, "\7in-addr\4arpa\0", 14);
|
||||||
ngx_memcpy(p, "\7in-addr\4arpa\0\0\14\0\1", 18);
|
}
|
||||||
|
|
||||||
rn->qlen = (u_short)
|
/* query type "PTR", IN query class */
|
||||||
(p + sizeof("\7in-addr\4arpa") + sizeof(ngx_resolver_qs_t)
|
p = ngx_cpymem(p, "\0\14\0\1", 4);
|
||||||
- rn->query);
|
|
||||||
|
rn->qlen = (u_short) (p - rn->query);
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,11 @@ typedef struct {
|
|||||||
/* PTR: resolved name, A: name to resolve */
|
/* PTR: resolved name, A: name to resolve */
|
||||||
u_char *name;
|
u_char *name;
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
/* PTR: IPv6 address to resolve (IPv4 address is in rbtree node key) */
|
||||||
|
struct in6_addr addr6;
|
||||||
|
#endif
|
||||||
|
|
||||||
u_short nlen;
|
u_short nlen;
|
||||||
u_short qlen;
|
u_short qlen;
|
||||||
|
|
||||||
@ -100,6 +105,13 @@ typedef struct {
|
|||||||
ngx_queue_t name_expire_queue;
|
ngx_queue_t name_expire_queue;
|
||||||
ngx_queue_t addr_expire_queue;
|
ngx_queue_t addr_expire_queue;
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
ngx_rbtree_t addr6_rbtree;
|
||||||
|
ngx_rbtree_node_t addr6_sentinel;
|
||||||
|
ngx_queue_t addr6_resend_queue;
|
||||||
|
ngx_queue_t addr6_expire_queue;
|
||||||
|
#endif
|
||||||
|
|
||||||
time_t resend_timeout;
|
time_t resend_timeout;
|
||||||
time_t expire;
|
time_t expire;
|
||||||
time_t valid;
|
time_t valid;
|
||||||
|
Loading…
Reference in New Issue
Block a user