IPv6 support in resolver

ToSHiC toshic.toshic at gmail.com
Wed Jul 10 17:32:55 UTC 2013


commit f194edc7e351d3a487e9305935647f0587b65fca
Author: Anton Kortunov <toshic.toshic at gmail.com>
Date:   Wed Jul 10 20:53:21 2013 +0400

    IPv6 support in mail server

    Client ip address is resolving to hostname even if it's IPv6 address.
    Forward resolve of this hostname is processed according to socket
family.

diff --git a/src/mail/ngx_mail_smtp_handler.c
b/src/mail/ngx_mail_smtp_handler.c
index 2171423..481e4a4 100644
--- a/src/mail/ngx_mail_smtp_handler.c
+++ b/src/mail/ngx_mail_smtp_handler.c
@@ -56,6 +56,9 @@ void
 ngx_mail_smtp_init_session(ngx_mail_session_t *s, ngx_connection_t *c)
 {
     struct sockaddr_in        *sin;
+#if (NGX_HAVE_INET6)
+    struct sockaddr_in6       *sin6;
+#endif
     ngx_resolver_ctx_t        *ctx;
     ngx_mail_core_srv_conf_t  *cscf;

@@ -67,7 +70,11 @@ ngx_mail_smtp_init_session(ngx_mail_session_t *s,
ngx_connection_t *c)
         return;
     }

-    if (c->sockaddr->sa_family != AF_INET) {
+    if (c->sockaddr->sa_family != AF_INET
+#if (NGX_HAVE_INET6)
+        && c->sockaddr->sa_family != AF_INET6
+#endif
+                                        ) {
         s->host = smtp_tempunavail;
         ngx_mail_smtp_greeting(s, c);
         return;
@@ -81,11 +88,23 @@ ngx_mail_smtp_init_session(ngx_mail_session_t *s,
ngx_connection_t *c)
         return;
     }

-    /* AF_INET only */
+    ctx->addr.family = c->sockaddr->sa_family;

-    sin = (struct sockaddr_in *) c->sockaddr;
+    switch (c->sockaddr->sa_family) {
+
+    case AF_INET:
+        sin = (struct sockaddr_in *) c->sockaddr;
+        ctx->addr.u.v4 = sin->sin_addr.s_addr;
+        break;
+
+#if (NGX_HAVE_INET6)
+    case AF_INET6:
+        sin6 = (struct sockaddr_in6 *) c->sockaddr;
+        ctx->addr.u.v6 = sin6->sin6_addr;
+        break;
+#endif
+    }

-    ctx->addr = sin->sin_addr.s_addr;
     ctx->handler = ngx_mail_smtp_resolve_addr_handler;
     ctx->data = s;
     ctx->timeout = cscf->resolver_timeout;
@@ -167,11 +186,23 @@ ngx_mail_smtp_resolve_name(ngx_event_t *rev)
     }

     ctx->name = s->host;
-    ctx->type = NGX_RESOLVE_A;
     ctx->handler = ngx_mail_smtp_resolve_name_handler;
     ctx->data = s;
     ctx->timeout = cscf->resolver_timeout;

+    switch (c->sockaddr->sa_family) {
+
+    case AF_INET:
+        ctx->type = NGX_RESOLVE_A;
+        break;
+
+#if (NGX_HAVE_INET6)
+    case AF_INET6:
+        ctx->type = NGX_RESOLVE_AAAA_A;
+        break;
+#endif
+    }
+
     if (ngx_resolve_name(ctx) != NGX_OK) {
         ngx_mail_close_connection(c);
     }
@@ -181,10 +212,13 @@ ngx_mail_smtp_resolve_name(ngx_event_t *rev)
 static void
 ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx)
 {
-    in_addr_t            addr;
+    ngx_ipaddr_t         addr;
     ngx_uint_t           i;
     ngx_connection_t    *c;
     struct sockaddr_in  *sin;
+#if (NGX_HAVE_INET6)
+    struct sockaddr_in6 *sin6;
+#endif
     ngx_mail_session_t  *s;

     s = ctx->data;
@@ -205,23 +239,55 @@ ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t
*ctx)

     } else {

-        /* AF_INET only */
+        addr.family = c->sockaddr->sa_family;

-        sin = (struct sockaddr_in *) c->sockaddr;
+        switch (c->sockaddr->sa_family) {
+
+        case AF_INET:
+            sin = (struct sockaddr_in *) c->sockaddr;
+            addr.u.v4 = sin->sin_addr.s_addr;
+            break;
+
+#if (NGX_HAVE_INET6)
+        case AF_INET6:
+            sin6 = (struct sockaddr_in6 *) c->sockaddr;
+            addr.u.v6 = sin6->sin6_addr;
+            break;
+#endif
+        }

         for (i = 0; i < ctx->naddrs; i++) {

-            addr = ctx->addrs[i];
+#if (NGX_DEBUG)
+            {
+                u_char      text[NGX_SOCKADDR_STRLEN];
+
+                ngx_inet_ntop(ctx->addrs[i].family, &ctx->addrs[i].u,
text, NGX_SOCKADDR_STRLEN);
+
+                ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
+                               "name was resolved to %s", text);
+            }
+#endif
+
+            if (addr.family != ctx->addrs[i].family) {
+                continue;
+            }

-            ngx_log_debug4(NGX_LOG_DEBUG_MAIL, c->log, 0,
-                           "name was resolved to %ud.%ud.%ud.%ud",
-                           (ntohl(addr) >> 24) & 0xff,
-                           (ntohl(addr) >> 16) & 0xff,
-                           (ntohl(addr) >> 8) & 0xff,
-                           ntohl(addr) & 0xff);
+            switch (addr.family) {

-            if (addr == sin->sin_addr.s_addr) {
-                goto found;
+            case AF_INET:
+                if (addr.u.v4 == ctx->addrs[i].u.v4) {
+                    goto found;
+                }
+                break;
+
+#if (NGX_HAVE_INET6)
+            case AF_INET6:
+                if (!ngx_memcmp(&addr.u.v6, &ctx->addrs[i].u.v6,
sizeof(addr.u.v6))) {
+                    goto found;
+                }
+                break;
+#endif
             }
         }



On Wed, Jul 10, 2013 at 9:30 PM, ToSHiC <toshic.toshic at gmail.com> wrote:

> commit 2bf37859004e3ff2b5dd9a11e1725153ca43ff32
> Author: Anton Kortunov <toshic.toshic at gmail.com>
> Date:   Wed Jul 10 20:49:28 2013 +0400
>
>     IPv6 support in http server upstreams
>
>     Try to resolve upstream server name to IPv4 address first, then to
> IPv6.
>
> diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
> index 16e6602..df522f7 100644
> --- a/src/http/ngx_http_upstream.c
> +++ b/src/http/ngx_http_upstream.c
> @@ -638,7 +638,11 @@ ngx_http_upstream_init_request(ngx_http_request_t *r)
>          }
>
>          ctx->name = *host;
> +#if (NGX_HAVE_INET6)
> +        ctx->type = NGX_RESOLVE_A_AAAA;
> +#else
>          ctx->type = NGX_RESOLVE_A;
> +#endif
>          ctx->handler = ngx_http_upstream_resolve_handler;
>          ctx->data = r;
>          ctx->timeout = clcf->resolver_timeout;
> @@ -912,16 +916,14 @@ ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t
> *ctx)
>
>  #if (NGX_DEBUG)
>      {
> -    in_addr_t   addr;
> +    u_char      text[NGX_SOCKADDR_STRLEN];
>      ngx_uint_t  i;
>
> -    for (i = 0; i < ctx->naddrs; i++) {
> -        addr = ntohl(ur->addrs[i]);
> +    for (i = 0; i < ur->naddrs; i++) {
> +        ngx_inet_ntop(ur->addrs[i].family, &ur->addrs[i].u, text,
> NGX_SOCKADDR_STRLEN);
>
> -        ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
> -                       "name was resolved to %ud.%ud.%ud.%ud",
> -                       (addr >> 24) & 0xff, (addr >> 16) & 0xff,
> -                       (addr >> 8) & 0xff, addr & 0xff);
> +        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
> +                       "name was resolved to %s", text);
>      }
>      }
>  #endif
> diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
> index fd4e36b..9e88a9a 100644
> --- a/src/http/ngx_http_upstream.h
> +++ b/src/http/ngx_http_upstream.h
> @@ -254,7 +254,7 @@ typedef struct {
>      ngx_uint_t                       no_port; /* unsigned no_port:1 */
>
>      ngx_uint_t                       naddrs;
> -    in_addr_t                       *addrs;
> +    ngx_ipaddr_t                    *addrs;
>
>      struct sockaddr                 *sockaddr;
>      socklen_t                        socklen;
> diff --git a/src/http/ngx_http_upstream_round_robin.c
> b/src/http/ngx_http_upstream_round_robin.c
> index e0c6c58..cf9d6a0 100644
> --- a/src/http/ngx_http_upstream_round_robin.c
> +++ b/src/http/ngx_http_upstream_round_robin.c
> @@ -268,6 +268,9 @@
> ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r,
>      size_t                             len;
>      ngx_uint_t                         i, n;
>      struct sockaddr_in                *sin;
> +#if (NGX_HAVE_INET6)
> +    struct sockaddr_in6               *sin6;
> +#endif
>      ngx_http_upstream_rr_peers_t      *peers;
>      ngx_http_upstream_rr_peer_data_t  *rrp;
>
> @@ -306,27 +309,52 @@
> ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r,
>
>          for (i = 0; i < ur->naddrs; i++) {
>
> -            len = NGX_INET_ADDRSTRLEN + sizeof(":65536") - 1;
> +            len = NGX_SOCKADDR_STRLEN;
>
>              p = ngx_pnalloc(r->pool, len);
>              if (p == NULL) {
>                  return NGX_ERROR;
>              }
>
> -            len = ngx_inet_ntop(AF_INET, &ur->addrs[i], p,
> NGX_INET_ADDRSTRLEN);
> +            len = ngx_inet_ntop(ur->addrs[i].family, &ur->addrs[i].u, p,
> NGX_SOCKADDR_STRLEN - sizeof(":65535") + 1);
>              len = ngx_sprintf(&p[len], ":%d", ur->port) - p;
>
> -            sin = ngx_pcalloc(r->pool, sizeof(struct sockaddr_in));
> -            if (sin == NULL) {
> +            switch (ur->addrs[i].family) {
> +
> +            case AF_INET:
> +                sin = ngx_pcalloc(r->pool, sizeof(struct sockaddr_in));
> +                if (sin == NULL) {
> +                    return NGX_ERROR;
> +                }
> +
> +                sin->sin_family = AF_INET;
> +                sin->sin_port = htons(ur->port);
> +                sin->sin_addr.s_addr = ur->addrs[i].u.v4;
> +
> +                peers->peer[i].sockaddr = (struct sockaddr *) sin;
> +                peers->peer[i].socklen = sizeof(struct sockaddr_in);
> +                break;
> +
> +#if (NGX_HAVE_INET6)
> +            case AF_INET6:
> +                sin6 = ngx_pcalloc(r->pool, sizeof(struct sockaddr_in6));
> +                if (sin6 == NULL) {
> +                    return NGX_ERROR;
> +                }
> +
> +                sin6->sin6_family = AF_INET6;
> +                sin6->sin6_port = htons(ur->port);
> +                sin6->sin6_addr = ur->addrs[i].u.v6;
> +
> +                peers->peer[i].sockaddr = (struct sockaddr *) sin6;
> +                peers->peer[i].socklen = sizeof(struct sockaddr_in6);
> +                break;
> +#endif
> +
> +            default:
>                  return NGX_ERROR;
>              }
>
> -            sin->sin_family = AF_INET;
> -            sin->sin_port = htons(ur->port);
> -            sin->sin_addr.s_addr = ur->addrs[i];
> -
> -            peers->peer[i].sockaddr = (struct sockaddr *) sin;
> -            peers->peer[i].socklen = sizeof(struct sockaddr_in);
>              peers->peer[i].name.len = len;
>              peers->peer[i].name.data = p;
>              peers->peer[i].weight = 1;
>
>
>
> On Wed, Jul 10, 2013 at 9:29 PM, ToSHiC <toshic.toshic at gmail.com> wrote:
>
>> 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/e05754ea/attachment-0001.html>


More information about the nginx-devel mailing list