IPv6 support in resolver
ToSHiC
toshic.toshic at gmail.com
Wed Jul 10 17:29:04 UTC 2013
commit 524dd02549575cb9ad5e95444093f6b494dc59bc
Author: Anton Kortunov <toshic.toshic at gmail.com>
Date: Wed Jul 10 20:43:59 2013 +0400
IPv6 reverse resolve support
diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
index 567368b..06d46c1 100644
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -71,7 +71,7 @@ static void ngx_resolver_process_response(ngx_resolver_t
*r, u_char *buf,
size_t n);
static void ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t
n,
ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan, ngx_uint_t ans);
-static void ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf,
size_t n,
+void ngx_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);
static ngx_resolver_node_t *ngx_resolver_lookup_name(ngx_resolver_t *r,
ngx_str_t *name, uint32_t hash);
@@ -126,7 +126,7 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names,
ngx_uint_t n)
ngx_resolver_rbtree_insert_value);
ngx_rbtree_init(&r->addr_rbtree, &r->addr_sentinel,
- ngx_rbtree_insert_value);
+ ngx_resolver_rbtree_insert_value);
ngx_queue_init(&r->name_resend_queue);
ngx_queue_init(&r->addr_resend_queue);
@@ -649,17 +649,40 @@ failed:
ngx_int_t
ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
{
+ uint32_t hash;
u_char *name;
ngx_resolver_t *r;
ngx_resolver_node_t *rn;
r = ctx->resolver;
+ rn = NULL;
+
+ hash = ctx->addr.family;
+
+ switch(ctx->addr.family) {
+
+ case AF_INET:
+ ctx->addr.u.v4 = ntohl(ctx->addr.u.v4);
+ ngx_crc32_update(&hash, (u_char *)&ctx->addr.u.v4,
sizeof(in_addr_t));
+ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
+ "resolve addr hash: %xd, addr:%xd, family: %d", hash,
ctx->addr.u.v4, ctx->addr.family);
+ break;
+
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ ngx_crc32_update(&hash, (u_char *)&ctx->addr.u.v6, sizeof(struct
in6_addr));
+ break;
+#endif
- ctx->addr = ntohl(ctx->addr);
+ default:
+ goto failed;
+ }
/* lock addr mutex */
- rn = ngx_resolver_lookup_addr(r, ctx->addr);
+ rn = ngx_resolver_lookup_addr(r, ctx->addr, hash);
+ ngx_log_error(r->log_level, r->log, 0,
+ "resolve: in resolve_addr searching, hash = %xd, rn =
%p", hash, rn);
if (rn) {
@@ -714,8 +737,10 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
goto failed;
}
- rn->node.key = ctx->addr;
+ rn->node.key = hash;
rn->query = NULL;
+ rn->qtype = ctx->type;
+ rn->u.addr = ctx->addr;
ngx_rbtree_insert(&r->addr_rbtree, &rn->node);
}
@@ -788,10 +813,11 @@ failed:
void
ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx)
{
- in_addr_t addr;
+ uint32_t hash;
ngx_resolver_t *r;
ngx_resolver_ctx_t *w, **p;
ngx_resolver_node_t *rn;
+ u_char text[NGX_SOCKADDR_STRLEN];
r = ctx->resolver;
@@ -806,7 +832,25 @@ ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx)
if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) {
- rn = ngx_resolver_lookup_addr(r, ctx->addr);
+ hash = ctx->addr.family;
+
+ switch(ctx->addr.family) {
+
+ case AF_INET:
+ ngx_crc32_update(&hash, (u_char *)&ctx->addr.u.v4,
sizeof(in_addr_t));
+ break;
+
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ ngx_crc32_update(&hash, (u_char *)&ctx->addr.u.v6,
sizeof(struct in6_addr));
+ break;
+#endif
+
+ default:
+ goto failed;
+ }
+
+ rn = ngx_resolver_lookup_addr(r, ctx->addr, hash);
if (rn) {
p = &rn->waiting;
@@ -824,12 +868,12 @@ ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx)
}
}
- addr = ntohl(ctx->addr);
+failed:
+
+ ngx_inet_ntop(ctx->addr.family, &ctx->addr.u, text,
NGX_SOCKADDR_STRLEN);
ngx_log_error(NGX_LOG_ALERT, r->log, 0,
- "could not cancel %ud.%ud.%ud.%ud resolving",
- (addr >> 24) & 0xff, (addr >> 16) & 0xff,
- (addr >> 8) & 0xff, addr & 0xff);
+ "could not cancel %s resolving", text);
}
done:
@@ -1582,13 +1626,14 @@ failed:
}
-static void
+void
ngx_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;
+ char *err = NULL;
+ uint32_t hash = 0;
size_t len;
- in_addr_t addr;
+ ngx_ipaddr_t addr;
int32_t ttl;
ngx_int_t digit;
ngx_str_t name;
@@ -1596,12 +1641,16 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char
*buf, size_t n,
ngx_resolver_an_t *an;
ngx_resolver_ctx_t *ctx, *next;
ngx_resolver_node_t *rn;
+ u_char text[NGX_SOCKADDR_STRLEN];
if (ngx_resolver_copy(r, NULL, buf, &buf[12], &buf[n]) != NGX_OK) {
goto invalid_in_addr_arpa;
}
- addr = 0;
+ ngx_memzero(&addr, sizeof(ngx_ipaddr_t));
+
+ /* Try to parse request as in-addr.arpa */
+ addr.family = AF_INET;
i = 12;
for (mask = 0; mask < 32; mask += 8) {
@@ -1612,7 +1661,7 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char
*buf, size_t n,
goto invalid_in_addr_arpa;
}
- addr += digit << mask;
+ addr.u.v4 += digit << mask;
i += len;
}
@@ -1620,15 +1669,79 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char
*buf, size_t n,
goto invalid_in_addr_arpa;
}
+ i += sizeof("\7in-addr\4arpa") + sizeof(ngx_resolver_qs_t);
+
+ goto found;
+
+invalid_in_addr_arpa:
+
+#if (NGX_HAVE_INET6)
+ /* Try to parse request as ip6.arpa */
+ addr.family = AF_INET6;
+ i = 12;
+
+ for (len = 15; len < 16; len--) {
+ if (buf[i++] != 1)
+ goto invalid_arpa;
+
+ digit = ngx_hextoi(&buf[i++], 1);
+ if (digit == NGX_ERROR || digit > 16) {
+ goto invalid_arpa;
+ }
+
+ addr.u.v6.s6_addr[len] = digit;
+
+ if (buf[i++] != 1)
+ goto invalid_arpa;
+
+
+ digit = ngx_hextoi(&buf[i++], 1);
+ if (digit == NGX_ERROR || digit > 16) {
+ goto invalid_arpa;
+ }
+
+ addr.u.v6.s6_addr[len] += digit << 4;
+ }
+
+ if (ngx_strcmp(&buf[i], "\3ip6\4arpa") != 0) {
+ goto invalid_arpa;
+ }
+
+ i += sizeof("\3ip6\4arpa") + sizeof(ngx_resolver_qs_t);
+
+#else /* NGX_HAVE_INET6 */
+ goto invalid_arpa;
+#endif
+
+found:
+
/* lock addr mutex */
- rn = ngx_resolver_lookup_addr(r, addr);
+ hash = addr.family;
+
+ switch(addr.family) {
+
+ case AF_INET:
+ ngx_crc32_update(&hash, (u_char *)&addr.u.v4, sizeof(in_addr_t));
+ break;
+
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ ngx_crc32_update(&hash, (u_char *)&addr.u.v6, sizeof(struct
in6_addr));
+ break;
+#endif
+
+ default:
+ goto invalid;
+ }
+
+ rn = ngx_resolver_lookup_addr(r, addr, hash);
+
+ ngx_inet_ntop(addr.family, &addr.u, text, NGX_SOCKADDR_STRLEN);
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);
+ "unexpected response for %s", text);
goto failed;
}
@@ -1636,12 +1749,15 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char
*buf, size_t n,
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);
+ "wrong ident %ui response for %s, expect %ui",
+ ident, text, qident);
goto failed;
}
+ ngx_log_error(r->log_level, r->log, 0,
+ "code: %d, nan: %d",
+ code, nan);
+
if (code == 0 && nan == 0) {
code = 3; /* NXDOMAIN */
}
@@ -1669,8 +1785,6 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char
*buf, size_t n,
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;
}
@@ -1750,10 +1864,10 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char
*buf, size_t n,
return;
-invalid_in_addr_arpa:
+invalid_arpa:
ngx_log_error(r->log_level, r->log, 0,
- "invalid in-addr.arpa name in DNS response");
+ "invalid in-addr.arpa or ip6.arpa name in DNS response");
return;
short_response:
@@ -1818,28 +1932,54 @@ ngx_resolver_lookup_name(ngx_resolver_t *r,
ngx_str_t *name, uint32_t hash)
static ngx_resolver_node_t *
-ngx_resolver_lookup_addr(ngx_resolver_t *r, in_addr_t addr)
+ngx_resolver_lookup_addr(ngx_resolver_t *r, ngx_ipaddr_t addr, uint32_t
hash)
{
+ ngx_int_t rc;
ngx_rbtree_node_t *node, *sentinel;
+ ngx_resolver_node_t *rn;
node = r->addr_rbtree.root;
sentinel = r->addr_rbtree.sentinel;
while (node != sentinel) {
- if (addr < node->key) {
+ if (hash < node->key) {
node = node->left;
continue;
}
- if (addr > node->key) {
+ if (hash > node->key) {
node = node->right;
continue;
}
- /* addr == node->key */
+ /* hash == node->key */
+
+ rn = (ngx_resolver_node_t *) node;
+
+ rc = addr.family - rn->u.addr.family;
+
+ if (rc == 0) {
+
+ switch (addr.family) {
+ case AF_INET:
+ rc = ngx_memn2cmp((u_char *)&addr.u.v4, (u_char
*)&rn->u.addr.u.v4, sizeof(in_addr_t), sizeof(in_addr_t));
+ break;
+
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ rc = ngx_memn2cmp((u_char *)&addr.u.v6, (u_char
*)&rn->u.addr.u.v6, sizeof(struct in6_addr), sizeof(struct in6_addr));
+ break;
+#endif
+ }
+
+ if (rc == 0) {
+ return rn;
+ }
- return (ngx_resolver_node_t *) node;
+ }
+
+ node = (rc < 0) ? node->left : node->right;
}
/* not found */
@@ -1854,6 +1994,7 @@ ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t
*temp,
{
ngx_rbtree_node_t **p;
ngx_resolver_node_t *rn, *rn_temp;
+ ngx_int_t rc;
for ( ;; ) {
@@ -1870,8 +2011,29 @@ ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t
*temp,
rn = (ngx_resolver_node_t *) node;
rn_temp = (ngx_resolver_node_t *) temp;
- p = (ngx_memn2cmp(rn->name, rn_temp->name, rn->nlen,
rn_temp->nlen)
- < 0) ? &temp->left : &temp->right;
+ if (rn->qtype == NGX_RESOLVE_PTR) {
+ rc = rn->u.addr.family - rn_temp->u.addr.family;
+
+ if (rc == 0) {
+
+ switch (rn->u.addr.family) {
+ case AF_INET:
+ rc = ngx_memn2cmp((u_char *)&rn->u.addr.u.v4,
(u_char *)&rn_temp->u.addr.u.v4, sizeof(in_addr_t), sizeof(in_addr_t));
+ break;
+
+ #if (NGX_HAVE_INET6)
+ case AF_INET6:
+ rc = ngx_memn2cmp((u_char *)&rn->u.addr.u.v6,
(u_char *)&rn_temp->u.addr.u.v6, sizeof(struct in6_addr), sizeof(struct
in6_addr));
+ break;
+ #endif
+ }
+ }
+
+ } else {
+ rc = ngx_memn2cmp(rn->name, rn_temp->name, rn->nlen,
rn_temp->nlen);
+ }
+
+ p = (rc < 0) ? &temp->left : &temp->right;
}
if (*p == sentinel) {
@@ -1989,8 +2151,6 @@ ngx_resolver_create_name_query(ngx_resolver_node_t
*rn, ngx_resolver_ctx_t *ctx)
}
-/* AF_INET only */
-
static ngx_int_t
ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t
*ctx)
{
@@ -2001,7 +2161,7 @@ ngx_resolver_create_addr_query(ngx_resolver_node_t
*rn, ngx_resolver_ctx_t *ctx)
ngx_resolver_query_t *query;
len = sizeof(ngx_resolver_query_t)
- + sizeof(".255.255.255.255.in-addr.arpa.") - 1
+ + NGX_PTR_QUERY_LEN
+ sizeof(ngx_resolver_qs_t);
p = ngx_resolver_alloc(ctx->resolver, len);
@@ -2028,18 +2188,50 @@ ngx_resolver_create_addr_query(ngx_resolver_node_t
*rn, ngx_resolver_ctx_t *ctx)
p += sizeof(ngx_resolver_query_t);
- for (n = 0; n < 32; n += 8) {
- d = ngx_sprintf(&p[1], "%ud", (ctx->addr >> n) & 0xff);
- *p = (u_char) (d - &p[1]);
- p = d;
+ switch (ctx->addr.family) {
+
+ case AF_INET:
+ for (n = 0; n < 32; n += 8) {
+ d = ngx_sprintf(&p[1], "%ud", (ctx->addr.u.v4 >> n) & 0xff);
+ *p = (u_char) (d - &p[1]);
+ p = d;
+ }
+
+ /* query type "PTR", IP query class */
+ ngx_memcpy(p, "\7in-addr\4arpa\0\0\14\0\1", 18);
+
+ rn->qlen = (u_short)
+ (p + sizeof("\7in-addr\4arpa") +
sizeof(ngx_resolver_qs_t)
+ - rn->query);
+
+ break;
+
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ for (n = 15; n >= 0; n--) {
+ p = ngx_sprintf(p, "\1%xd\1%xd",
+ (ctx->addr.u.v6.s6_addr[n]) & 0xf,
+ (ctx->addr.u.v6.s6_addr[n] >> 4) & 0xf);
+
+ }
+
+ /* query type "PTR", IP query class */
+ ngx_memcpy(p, "\3ip6\4arpa\0\0\14\0\1", 18);
+
+ rn->qlen = (u_short)
+ (p + sizeof("\3ip6\4arpa") +
sizeof(ngx_resolver_qs_t)
+ - rn->query);
+
+ break;
+#endif
+
+ default:
+ return NGX_ERROR;
}
- /* query type "PTR", IP query class */
- ngx_memcpy(p, "\7in-addr\4arpa\0\0\14\0\1", 18);
+ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0,
+ "resolve: query %s, ident %i", (rn->query+12), ident &
0xffff);
- rn->qlen = (u_short)
- (p + sizeof("\7in-addr\4arpa") +
sizeof(ngx_resolver_qs_t)
- - rn->query);
return NGX_OK;
}
diff --git a/src/core/ngx_resolver.h b/src/core/ngx_resolver.h
index d2a4606..a45b244 100644
--- a/src/core/ngx_resolver.h
+++ b/src/core/ngx_resolver.h
@@ -41,6 +41,11 @@
#define NGX_RESOLVER_MAX_RECURSION 50
+#if (NGX_HAVE_INET6)
+#define NGX_PTR_QUERY_LEN
(sizeof(".f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.ip6.arpa.")
- 1)
+#else
+#define NGX_PTR_QUERY_LEN (sizeof(".255.255.255.255.in-addr.arpa.") - 1)
+#endif
typedef struct {
ngx_connection_t *connection;
On Wed, Jul 10, 2013 at 9:24 PM, ToSHiC <toshic.toshic at gmail.com> wrote:
> commit 8670b164784032b2911b3c34ac31ef52ddba5b60
> Author: Anton Kortunov <toshic.toshic at gmail.com>
> Date: Wed Jul 10 19:53:06 2013 +0400
>
> IPv6 support in resolver for forward requests
>
> To resolve name into IPv6 address use NGX_RESOLVE_AAAA,
> NGX_RESOLVE_A_AAAA or NGX_RESOLVE_AAAA_A record type instead of
> NGX_RESOLVE_A
>
> diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
> index d59d0c4..567368b 100644
> --- a/src/core/ngx_resolver.c
> +++ b/src/core/ngx_resolver.c
> @@ -76,7 +76,7 @@ static void ngx_resolver_process_ptr(ngx_resolver_t *r,
> u_char *buf, size_t n,
> static ngx_resolver_node_t *ngx_resolver_lookup_name(ngx_resolver_t *r,
> ngx_str_t *name, uint32_t hash);
> static ngx_resolver_node_t *ngx_resolver_lookup_addr(ngx_resolver_t *r,
> - in_addr_t addr);
> + ngx_ipaddr_t addr, uint32_t hash);
> static void ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp,
> ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
> static ngx_int_t ngx_resolver_copy(ngx_resolver_t *r, ngx_str_t *name,
> @@ -88,7 +88,7 @@ static void *ngx_resolver_calloc(ngx_resolver_t *r,
> size_t size);
> static void ngx_resolver_free(ngx_resolver_t *r, void *p);
> static void ngx_resolver_free_locked(ngx_resolver_t *r, void *p);
> static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size);
> -static in_addr_t *ngx_resolver_rotate(ngx_resolver_t *r, in_addr_t *src,
> +static ngx_ipaddr_t *ngx_resolver_rotate(ngx_resolver_t *r, ngx_ipaddr_t
> *src,
> ngx_uint_t n);
> static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t
> len);
>
> @@ -270,13 +270,27 @@ ngx_resolver_cleanup_tree(ngx_resolver_t *r,
> ngx_rbtree_t *tree)
> ngx_resolver_ctx_t *
> ngx_resolve_start(ngx_resolver_t *r, ngx_resolver_ctx_t *temp)
> {
> - in_addr_t addr;
> + ngx_ipaddr_t addr;
> ngx_resolver_ctx_t *ctx;
>
> if (temp) {
> - addr = ngx_inet_addr(temp->name.data, temp->name.len);
> + addr.family = 0;
>
> - if (addr != INADDR_NONE) {
> +
> + addr.u.v4 = ngx_inet_addr(temp->name.data, temp->name.len);
> +
> + if (addr.u.v4 != INADDR_NONE) {
> +
> + addr.family = AF_INET;
> +
> +#if (NGX_HAVE_INET6)
> + } else if (ngx_inet6_addr(temp->name.data, temp->name.len,
> addr.u.v6.s6_addr) == NGX_OK) {
> +
> + addr.family = AF_INET6;
> +#endif
> + }
> +
> + if (addr.family) {
> temp->resolver = r;
> temp->state = NGX_OK;
> temp->naddrs = 1;
> @@ -417,7 +431,7 @@ static ngx_int_t
> ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
> {
> uint32_t hash;
> - in_addr_t addr, *addrs;
> + ngx_ipaddr_t addr, *addrs;
> ngx_int_t rc;
> ngx_uint_t naddrs;
> ngx_resolver_ctx_t *next;
> @@ -429,7 +443,11 @@ ngx_resolve_name_locked(ngx_resolver_t *r,
> ngx_resolver_ctx_t *ctx)
>
> if (rn) {
>
> - if (rn->valid >= ngx_time()) {
> + if (rn->valid >= ngx_time()
> +#if (NGX_HAVE_INET6)
> + && rn->qtype != NGX_RESOLVE_RETRY
> +#endif
> + ) {
>
> ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0, "resolve
> cached");
>
> @@ -446,7 +464,6 @@ ngx_resolve_name_locked(ngx_resolver_t *r,
> ngx_resolver_ctx_t *ctx)
> /* NGX_RESOLVE_A answer */
>
> if (naddrs != 1) {
> - addr = 0;
> addrs = ngx_resolver_rotate(r, rn->u.addrs, naddrs);
> if (addrs == NULL) {
> return NGX_ERROR;
> @@ -506,6 +523,8 @@ ngx_resolve_name_locked(ngx_resolver_t *r,
> ngx_resolver_ctx_t *ctx)
> } while (ctx);
>
> return NGX_OK;
> + } else {
> + rn->qtype = ctx->type;
> }
>
> if (rn->waiting) {
> @@ -552,6 +571,7 @@ ngx_resolve_name_locked(ngx_resolver_t *r,
> ngx_resolver_ctx_t *ctx)
> rn->node.key = hash;
> rn->nlen = (u_short) ctx->name.len;
> rn->query = NULL;
> + rn->qtype = ctx->type;
>
> ngx_rbtree_insert(&r->name_rbtree, &rn->node);
> }
> @@ -1130,6 +1150,9 @@ found:
> switch (qtype) {
>
> case NGX_RESOLVE_A:
> +#if (NGX_HAVE_INET6)
> + case NGX_RESOLVE_AAAA:
> +#endif
>
> ngx_resolver_process_a(r, buf, n, ident, code, nan,
> i + sizeof(ngx_resolver_qs_t));
> @@ -1178,7 +1201,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char
> *buf, size_t last,
> size_t len;
> int32_t ttl;
> uint32_t hash;
> - in_addr_t addr, *addrs;
> + ngx_ipaddr_t addr, *addrs;
> ngx_str_t name;
> ngx_uint_t qtype, qident, naddrs, a, i, n, start;
> ngx_resolver_an_t *an;
> @@ -1212,12 +1235,57 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char
> *buf, size_t last,
> goto failed;
> }
>
> - ngx_resolver_free(r, name.data);
> -
> if (code == 0 && nan == 0) {
> +
> +#if (NGX_HAVE_INET6)
> + /*
> + * If it was required dual type v4|v6 resolv create one more request
> + */
> + if (rn->qtype == NGX_RESOLVE_A_AAAA
> + || rn->qtype == NGX_RESOLVE_AAAA_A) {
> +
> + ngx_queue_remove(&rn->queue);
> +
> + rn->valid = ngx_time() + (r->valid ? r->valid : ttl);
> + 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;
> +
> + switch (rn->qtype) {
> +
> + case NGX_RESOLVE_A_AAAA:
> + ctx->type = NGX_RESOLVE_AAAA;
> + break;
> +
> + case NGX_RESOLVE_AAAA_A:
> + ctx->type = NGX_RESOLVE_A;
> + break;
> + }
> +
> + ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,
> + "restarting request for name %V, with type
> %ud",
> + &name, ctx->type);
> +
> + rn->qtype = NGX_RESOLVE_RETRY;
> +
> + (void) ngx_resolve_name_locked(r, ctx);
> + }
> +
> + return;
> + }
> +#endif
> +
> code = 3; /* NXDOMAIN */
> }
>
> + ngx_resolver_free(r, name.data);
> +
> if (code) {
> next = rn->waiting;
> rn->waiting = NULL;
> @@ -1243,7 +1311,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char
> *buf, size_t last,
>
> i = ans;
> naddrs = 0;
> - addr = 0;
> + addr.family = 0;
> addrs = NULL;
> cname = NULL;
> qtype = 0;
> @@ -1302,13 +1370,30 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char
> *buf, size_t last,
> goto short_response;
> }
>
> - addr = htonl((buf[i] << 24) + (buf[i + 1] << 16)
> + addr.family = AF_INET;
> + addr.u.v4 = htonl((buf[i] << 24) + (buf[i + 1] << 16)
> + (buf[i + 2] << 8) + (buf[i + 3]));
>
> naddrs++;
>
> i += len;
>
> +#if (NGX_HAVE_INET6)
> + } else if (qtype == NGX_RESOLVE_AAAA) {
> +
> + i += sizeof(ngx_resolver_an_t);
> +
> + if (i + len > last) {
> + goto short_response;
> + }
> +
> + addr.family = AF_INET6;
> + ngx_memcpy(&addr.u.v6.s6_addr, &buf[i], 16);
> +
> + naddrs++;
> +
> + i += len;
> +#endif
> } else if (qtype == NGX_RESOLVE_CNAME) {
> cname = &buf[i] + sizeof(ngx_resolver_an_t);
> i += sizeof(ngx_resolver_an_t) + len;
> @@ -1333,7 +1418,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char
> *buf, size_t last,
>
> } else {
>
> - addrs = ngx_resolver_alloc(r, naddrs * sizeof(in_addr_t));
> + addrs = ngx_resolver_alloc(r, naddrs * sizeof(ngx_ipaddr_t));
> if (addrs == NULL) {
> return;
> }
> @@ -1369,12 +1454,23 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char
> *buf, size_t last,
>
> if (qtype == NGX_RESOLVE_A) {
>
> - addrs[n++] = htonl((buf[i] << 24) + (buf[i + 1] << 16)
> + addrs[n].family = AF_INET;
> + addrs[n++].u.v4 = htonl((buf[i] << 24) + (buf[i + 1]
> << 16)
> + (buf[i + 2] << 8) + (buf[i +
> 3]));
>
> if (n == naddrs) {
> break;
> }
> +#if (NGX_HAVE_INET6)
> + } else if (qtype == NGX_RESOLVE_AAAA) {
> +
> + addrs[n].family = AF_INET6;
> + ngx_memcpy(&addrs[n++].u.v6.s6_addr, &buf[i], 16);
> +
> + if (n == naddrs) {
> + break;
> + }
> +#endif
> }
>
> i += len;
> @@ -1383,7 +1479,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char
> *buf, size_t last,
> rn->u.addrs = addrs;
>
> addrs = ngx_resolver_dup(r, rn->u.addrs,
> - naddrs * sizeof(in_addr_t));
> + naddrs * sizeof(ngx_ipaddr_t));
> if (addrs == NULL) {
> return;
> }
> @@ -1838,7 +1934,20 @@ ngx_resolver_create_name_query(ngx_resolver_node_t
> *rn, ngx_resolver_ctx_t *ctx)
> qs = (ngx_resolver_qs_t *) p;
>
> /* query type */
> - qs->type_hi = 0; qs->type_lo = (u_char) ctx->type;
> + qs->type_hi = 0; qs->type_lo = (u_char) rn->qtype;
> +
> +#if (NGX_HAVE_INET6)
> + switch (rn->qtype) {
> +
> + case NGX_RESOLVE_A_AAAA:
> + qs->type_lo = NGX_RESOLVE_A;
> + break;
> +
> + case NGX_RESOLVE_AAAA_A:
> + qs->type_lo = NGX_RESOLVE_AAAA;
> + break;
> + }
> +#endif
>
> /* IP query class */
> qs->class_hi = 0; qs->class_lo = 1;
> @@ -2136,13 +2245,13 @@ ngx_resolver_dup(ngx_resolver_t *r, void *src,
> size_t size)
> }
>
>
> -static in_addr_t *
> -ngx_resolver_rotate(ngx_resolver_t *r, in_addr_t *src, ngx_uint_t n)
> +static ngx_ipaddr_t *
> +ngx_resolver_rotate(ngx_resolver_t *r, ngx_ipaddr_t *src, ngx_uint_t n)
> {
> void *dst, *p;
> ngx_uint_t j;
>
> - dst = ngx_resolver_alloc(r, n * sizeof(in_addr_t));
> + dst = ngx_resolver_alloc(r, n * sizeof(ngx_ipaddr_t));
>
> if (dst == NULL) {
> return dst;
> @@ -2151,12 +2260,12 @@ ngx_resolver_rotate(ngx_resolver_t *r, in_addr_t
> *src, ngx_uint_t n)
> j = ngx_random() % n;
>
> if (j == 0) {
> - ngx_memcpy(dst, src, n * sizeof(in_addr_t));
> + ngx_memcpy(dst, src, n * sizeof(ngx_ipaddr_t));
> return dst;
> }
>
> - p = ngx_cpymem(dst, &src[j], (n - j) * sizeof(in_addr_t));
> - ngx_memcpy(p, src, j * sizeof(in_addr_t));
> + p = ngx_cpymem(dst, &src[j], (n - j) * sizeof(ngx_ipaddr_t));
> + ngx_memcpy(p, src, j * sizeof(ngx_ipaddr_t));
>
> return dst;
> }
> diff --git a/src/core/ngx_resolver.h b/src/core/ngx_resolver.h
> index 6fd81fe..d2a4606 100644
> --- a/src/core/ngx_resolver.h
> +++ b/src/core/ngx_resolver.h
> @@ -67,10 +67,11 @@ typedef struct {
> u_short qlen;
>
> u_char *query;
> + ngx_int_t qtype;
>
> union {
> - in_addr_t addr;
> - in_addr_t *addrs;
> + ngx_ipaddr_t addr;
> + ngx_ipaddr_t *addrs;
> u_char *cname;
> } u;
>
> @@ -130,8 +131,8 @@ struct ngx_resolver_ctx_s {
> ngx_str_t name;
>
> ngx_uint_t naddrs;
> - in_addr_t *addrs;
> - in_addr_t addr;
> + ngx_ipaddr_t *addrs;
> + ngx_ipaddr_t addr;
>
> ngx_resolver_handler_pt handler;
> void *data;
>
>
>
> On Wed, Jul 10, 2013 at 9:17 PM, ToSHiC <toshic.toshic at gmail.com> wrote:
>
>> commit 482bd2a0b6240a2b26409b9c7924ad01c814f293
>> Author: Anton Kortunov <toshic.toshic at gmail.com>
>> Date: Wed Jul 10 13:21:27 2013 +0400
>>
>> Added NGX_RESOLVE_* constants
>>
>> Module developers can decide how to resolve hosts relating to IPv6:
>>
>> NGX_RESOLVE_AAAA - try to resolve only to IPv6 address
>> NGX_RESOLVE_AAAA_A - IPv6 is preferred (recommended by standards)
>> NGX_RESOLVE_A_AAAA - IPv4 is preferred (better strategy nowadays)
>>
>> diff --git a/src/core/ngx_resolver.h b/src/core/ngx_resolver.h
>> index ae34ca5..6fd81fe 100644
>> --- a/src/core/ngx_resolver.h
>> +++ b/src/core/ngx_resolver.h
>> @@ -20,6 +20,15 @@
>> #define NGX_RESOLVE_TXT 16
>> #define NGX_RESOLVE_DNAME 39
>>
>> +#if (NGX_HAVE_INET6)
>> +
>> +#define NGX_RESOLVE_AAAA 28
>> +#define NGX_RESOLVE_A_AAAA 1000
>> +#define NGX_RESOLVE_AAAA_A 1001
>> +#define NGX_RESOLVE_RETRY 1002
>> +
>> +#endif
>> +
>> #define NGX_RESOLVE_FORMERR 1
>> #define NGX_RESOLVE_SERVFAIL 2
>> #define NGX_RESOLVE_NXDOMAIN 3
>>
>>
>>
>> On Wed, Jul 10, 2013 at 9:17 PM, ToSHiC <toshic.toshic at gmail.com> wrote:
>>
>>> Hello,
>>>
>>> I've split this big patch into several small patches, taking into
>>> account your comments. I'll send each part in separate email. Here is the
>>> first one.
>>>
>>> commit 597d09e7ae9247c5466b18aa2ef3f5892e61b708
>>> Author: Anton Kortunov <toshic.toshic at gmail.com>
>>> Date: Wed Jul 10 13:14:52 2013 +0400
>>>
>>> Added new structure ngx_ipaddr_t
>>>
>>> This structure contains family field
>>> and the union of ipv4/ipv6 structures in_addr_t and in6_addr.
>>>
>>> diff --git a/src/core/ngx_inet.h b/src/core/ngx_inet.h
>>> index 6a5a368..077ed34 100644
>>> --- a/src/core/ngx_inet.h
>>> +++ b/src/core/ngx_inet.h
>>> @@ -68,6 +68,16 @@ typedef struct {
>>>
>>>
>>> typedef struct {
>>> + ngx_uint_t family;
>>> + union {
>>> + in_addr_t v4;
>>> +#if (NGX_HAVE_INET6)
>>> + struct in6_addr v6;
>>> +#endif
>>> + } u;
>>> +} ngx_ipaddr_t;
>>> +
>>> +typedef struct {
>>> struct sockaddr *sockaddr;
>>> socklen_t socklen;
>>> ngx_str_t name;
>>>
>>>
>>>
>>> On Mon, Jun 17, 2013 at 7:30 PM, Maxim Dounin <mdounin at mdounin.ru>wrote:
>>>
>>>> Hello!
>>>>
>>>> On Fri, Jun 14, 2013 at 09:44:46PM +0400, ToSHiC wrote:
>>>>
>>>> > Hello,
>>>> >
>>>> > We needed this feature in our company, I found that it is in
>>>> milestones of
>>>> > version 1.5 but doesn't exist yet. So I've implemented it based in
>>>> 1.3 code
>>>> > and merged in current 1.5 code. When I wrote this code I mostly cared
>>>> about
>>>> > minimum intrusion into other parts of nginx.
>>>> >
>>>> > IPv6 fallback logic is not a straightforward implementation of
>>>> suggested by
>>>> > RFC. RFC states that IPv6 resolving have priority over IPv4, and it's
>>>> not
>>>> > very good for Internet we have currently. With this patch you can
>>>> specify
>>>> > priority, and in upstream and mail modules I've set IPv4 as preferred
>>>> > address family.
>>>> >
>>>> > Patch is pretty big and I hope it'll not break mailing list or mail
>>>> clients.
>>>>
>>>> You may want to try to split the patch into smaller patches to
>>>> simplify review. See also some hints here:
>>>>
>>>> http://nginx.org/en/docs/contributing_changes.html
>>>>
>>>> Some quick comments below.
>>>>
>>>> [...]
>>>>
>>>> > - addr = ntohl(ctx->addr);
>>>> > +failed:
>>>> > +
>>>> > + //addr = ntohl(ctx->addr);
>>>> > + inet_ntop(ctx->addr.family, &ctx->addr.u, text,
>>>> > NGX_SOCKADDR_STRLEN);
>>>> >
>>>> > ngx_log_error(NGX_LOG_ALERT, r->log, 0,
>>>> > - "could not cancel %ud.%ud.%ud.%ud resolving",
>>>> > - (addr >> 24) & 0xff, (addr >> 16) & 0xff,
>>>> > - (addr >> 8) & 0xff, addr & 0xff);
>>>> > + "could not cancel %s resolving", text);
>>>>
>>>> 1. Don't use inet_ntop(), there is ngx_sock_ntop() instead.
>>>>
>>>> 2. Don't use C++ style ("//") comments.
>>>>
>>>> 3. If some data is only needed for debug logging, keep relevant
>>>> calculations under #if (NGX_DEBUG).
>>>>
>>>> [...]
>>>>
>>>> > @@ -334,6 +362,7 @@
>>>> > ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r,
>>>> > peers->peer[i].current_weight = 0;
>>>> > peers->peer[i].max_fails = 1;
>>>> > peers->peer[i].fail_timeout = 10;
>>>> > +
>>>> > }
>>>> > }
>>>> >
>>>>
>>>> Please avoid unrelated changes.
>>>>
>>>> [...]
>>>>
>>>> --
>>>> Maxim Dounin
>>>> http://nginx.org/en/donation.html
>>>>
>>>> _______________________________________________
>>>> nginx-devel mailing list
>>>> nginx-devel at nginx.org
>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel
>>>>
>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20130710/7b5c16ce/attachment-0001.html>
More information about the nginx-devel
mailing list