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