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

<div><br></div><div>    IPv6 reverse resolve support</div><div><br></div><div>diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c</div><div>index 567368b..06d46c1 100644</div><div>--- a/src/core/ngx_resolver.c</div>

<div>+++ b/src/core/ngx_resolver.c</div><div>@@ -71,7 +71,7 @@ static void ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf,</div><div class="im"><div>     size_t n);</div><div> static void ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,</div>

<div>     ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan, ngx_uint_t ans);</div><div>-static void ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,</div><div>+void ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,</div>

<div>     ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan);</div></div><div class="im"><div> static ngx_resolver_node_t *ngx_resolver_lookup_name(ngx_resolver_t *r,</div><div>     ngx_str_t *name, uint32_t hash);</div>
</div><div>@@ -126,7 +126,7 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)</div>
<div>                     ngx_resolver_rbtree_insert_value);</div><div><br></div><div>     ngx_rbtree_init(&r->addr_rbtree, &r->addr_sentinel,</div><div>-                    ngx_rbtree_insert_value);</div><div>

+                    ngx_resolver_rbtree_insert_value);</div><div><br></div><div>     ngx_queue_init(&r->name_resend_queue);</div><div>     ngx_queue_init(&r->addr_resend_queue);</div><div>@@ -649,17 +649,40 @@ failed:</div>
<div class="im">
<div> ngx_int_t</div><div> ngx_resolve_addr(ngx_resolver_ctx_t *ctx)</div><div> {</div><div>+    uint32_t              hash;</div><div>     u_char               *name;</div><div>     ngx_resolver_t       *r;</div><div>     ngx_resolver_node_t  *rn;</div>

<div><br></div><div>     r = ctx->resolver;</div><div>+    rn = NULL;</div><div>+</div><div>+    hash = ctx->addr.family;</div></div><div>+</div><div>+    switch(ctx->addr.family) {</div><div><div>+</div><div>+    case AF_INET:</div>
<div class="im">
<div>+        ctx->addr.u.v4 = ntohl(ctx->addr.u.v4);</div><div>+        ngx_crc32_update(&hash, (u_char *)&ctx->addr.u.v4, sizeof(in_addr_t));</div><div>+ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,</div>

<div>+               "resolve addr hash: %xd, addr:%xd, family: %d", hash, ctx->addr.u.v4, ctx->addr.family);</div><div>+        break;</div><div>+</div><div>+#if (NGX_HAVE_INET6)</div><div>+    case AF_INET6:</div>

<div>+        ngx_crc32_update(&hash, (u_char *)&ctx->addr.u.v6, sizeof(struct in6_addr));</div><div>+        break;</div><div>+#endif</div><div><br></div></div><div class="im"><div>-    ctx->addr = ntohl(ctx->addr);</div>
</div><div class="im"><div>
+    default:</div><div>+        goto failed;</div><div>+    }</div><div><br></div><div>     /* lock addr mutex */</div><div><br></div><div>-    rn = ngx_resolver_lookup_addr(r, ctx->addr);</div><div>+    rn = ngx_resolver_lookup_addr(r, ctx->addr, hash);</div>

<div>+    ngx_log_error(r->log_level, r->log, 0,</div><div>+                  "resolve: in resolve_addr searching, hash = %xd, rn = %p", hash, rn);</div><div><br></div><div>     if (rn) {</div><div><br></div>

</div><div>@@ -714,8 +737,10 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)</div><div class="im"><div>             goto failed;</div><div>         }</div><div><br></div><div>-        rn->node.key = ctx->addr;</div></div>
<div>+        rn->node.key = hash;</div><div class="im">
<div>         rn->query = NULL;</div><div>+        rn->qtype = ctx->type;</div></div><div class="im"><div>+        rn->u.addr = ctx->addr;</div><div><br></div><div>         ngx_rbtree_insert(&r->addr_rbtree, &rn->node);</div>

<div>     }</div></div><div>@@ -788,10 +813,11 @@ failed:</div><div> void</div><div> ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx)</div></div><div><div class="im"><div> {</div><div>-    in_addr_t             addr;</div>
<div>+    uint32_t              hash;</div>
<div>     ngx_resolver_t       *r;</div><div>     ngx_resolver_ctx_t   *w, **p;</div><div>     ngx_resolver_node_t  *rn;</div></div><div>+    u_char                text[NGX_SOCKADDR_STRLEN];</div><div><br></div><div>     r = ctx->resolver;</div>

<div><br></div><div>@@ -806,7 +832,25 @@ ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx)</div><div class="im"><div><br></div><div>     if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) {</div><div><br>
</div><div>-        rn = ngx_resolver_lookup_addr(r, ctx->addr);</div>
<div>+        hash = ctx->addr.family;</div><div>+</div><div>+        switch(ctx->addr.family) {</div><div>+</div><div>+        case AF_INET:</div><div>+            ngx_crc32_update(&hash, (u_char *)&ctx->addr.u.v4, sizeof(in_addr_t));</div>

<div>+            break;</div><div>+</div><div>+#if (NGX_HAVE_INET6)</div><div>+        case AF_INET6:</div><div>+            ngx_crc32_update(&hash, (u_char *)&ctx->addr.u.v6, sizeof(struct in6_addr));</div><div>

+            break;</div><div>+#endif</div><div>+</div><div>+        default:</div><div>+            goto failed;</div><div>+        }</div><div>+</div><div>+        rn = ngx_resolver_lookup_addr(r, ctx->addr, hash);</div>

<div><br></div><div>         if (rn) {</div><div>             p = &rn->waiting;</div></div><div>@@ -824,12 +868,12 @@ ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx)</div><div class="im"><div>             }</div><div>
         }</div><div>
<br></div><div>-        addr = ntohl(ctx->addr);</div><div>+failed:</div></div></div><div><div>+</div><div>+        ngx_inet_ntop(ctx->addr.family, &ctx->addr.u, text, NGX_SOCKADDR_STRLEN);</div><div class="im">
<div><br></div><div>
         ngx_log_error(NGX_LOG_ALERT, r->log, 0,</div><div>-                      "could not cancel %ud.%ud.%ud.%ud resolving",</div><div>-                      (addr >> 24) & 0xff, (addr >> 16) & 0xff,</div>

<div>-                      (addr >> 8) & 0xff, addr & 0xff);</div><div>+                      "could not cancel %s resolving", text);</div><div>     }</div><div><br></div></div><div> done:</div><div>
@@ -1582,13 +1626,14 @@ failed:</div>
<div> }</div><div><br></div><div><br></div><div>-static void</div><div>+void</div><div class="im"><div> ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,</div></div><div class="im"><div>     ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan)</div>

<div> {</div><div>-    char                 *err;</div><div>+    char                 *err = NULL;</div><div>+    uint32_t              hash = 0;</div><div>     size_t                len;</div></div><div class="im"><div>
-    in_addr_t             addr;</div>
<div>+    ngx_ipaddr_t          addr;</div></div><div class="im"><div>     int32_t               ttl;</div><div>     ngx_int_t             digit;</div><div>     ngx_str_t             name;</div></div><div>@@ -1596,12 +1641,16 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,</div>
<div class="im">
<div>     ngx_resolver_an_t    *an;</div><div>     ngx_resolver_ctx_t   *ctx, *next;</div><div>     ngx_resolver_node_t  *rn;</div></div><div>+    u_char                text[NGX_SOCKADDR_STRLEN];</div><div class="im"><div>
<br></div><div>     if (ngx_resolver_copy(r, NULL, buf, &buf[12], &buf[n]) != NGX_OK) {</div>
<div>         goto invalid_in_addr_arpa;</div><div>     }</div><div><br></div></div><div>-    addr = 0;</div><div class="im"><div>+    ngx_memzero(&addr, sizeof(ngx_ipaddr_t));</div><div>+</div><div>+    /* Try to parse request as in-addr.arpa */</div>

</div></div><div><div class="im"><div>+    addr.family = AF_INET;</div><div>     i = 12;</div><div><br></div><div>     for (mask = 0; mask < 32; mask += 8) {</div></div><div>@@ -1612,7 +1661,7 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,</div>
<div class="im">
<div>             goto invalid_in_addr_arpa;</div><div>         }</div><div><br></div><div>-        addr += digit << mask;</div><div>+        addr.u.v4 += digit << mask;</div><div>         i += len;</div><div>

     }</div><div><br></div></div><div>@@ -1620,15 +1669,79 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,</div><div class="im"><div>         goto invalid_in_addr_arpa;</div><div>     }</div><div><br>
</div><div>+    i += sizeof("\7in-addr\4arpa") + sizeof(ngx_resolver_qs_t);</div>
<div>+</div><div>+    goto found;</div><div>+</div><div>+invalid_in_addr_arpa:</div></div><div>+</div><div>+#if (NGX_HAVE_INET6)</div><div class="im"><div>+    /* Try to parse request as ip6.arpa */</div></div><div>+    addr.family = AF_INET6;</div>
<div><div class="h5">
<div>+    i = 12;</div><div>+</div><div>+    for (len = 15; len < 16; len--) {</div><div>+        if (buf[i++] != 1)</div><div>+            goto invalid_arpa;</div><div>+</div><div>+        digit = ngx_hextoi(&buf[i++], 1);</div>

<div>+        if (digit == NGX_ERROR || digit > 16) {</div><div>+            goto invalid_arpa;</div><div>+        }</div><div>+</div><div>+        addr.u.v6.s6_addr[len] = digit;</div><div>+</div><div>+        if (buf[i++] != 1)</div>

<div>+            goto invalid_arpa;</div><div>+</div><div>+</div></div></div></div><div><div class="h5"><div><div>+        digit = ngx_hextoi(&buf[i++], 1);</div><div>+        if (digit == NGX_ERROR || digit > 16) {</div>
<div>+            goto invalid_arpa;</div>
<div>+        }</div><div>+</div><div>+        addr.u.v6.s6_addr[len] += digit << 4;</div><div>+    }</div><div>+</div><div>+    if (ngx_strcmp(&buf[i], "\3ip6\4arpa") != 0) {</div><div>+        goto invalid_arpa;</div>

<div>+    }</div><div>+</div><div>+    i += sizeof("\3ip6\4arpa") + sizeof(ngx_resolver_qs_t);</div><div>+</div><div>+#else /* NGX_HAVE_INET6 */</div><div>+    goto invalid_arpa;</div><div>+#endif</div><div>+</div>

<div>+found:</div><div>+</div><div>     /* lock addr mutex */</div><div><br></div><div>-    rn = ngx_resolver_lookup_addr(r, addr);</div><div>+    hash = addr.family;</div><div>+</div><div>+    switch(addr.family) {</div>

<div>+</div><div>+    case AF_INET:</div><div>+        ngx_crc32_update(&hash, (u_char *)&addr.u.v4, sizeof(in_addr_t));</div><div>+        break;</div><div>+</div><div>+#if (NGX_HAVE_INET6)</div><div>+    case AF_INET6:</div>

<div>+        ngx_crc32_update(&hash, (u_char *)&addr.u.v6, sizeof(struct in6_addr));</div><div>+        break;</div><div>+#endif</div><div>+</div><div>+    default:</div><div>+        goto invalid;</div><div>+    }</div>

<div>+</div><div>+    rn = ngx_resolver_lookup_addr(r, addr, hash);</div><div>+</div></div></div></div><div><div>+    ngx_inet_ntop(addr.family, &addr.u, text, NGX_SOCKADDR_STRLEN);</div><div class="im"><div><br></div>
<div>     if (rn == NULL || rn->query == NULL) {</div>
<div>         ngx_log_error(r->log_level, r->log, 0,</div></div><div>-                      "unexpected response for %ud.%ud.%ud.%ud",</div><div class="im"><div>-                      (addr >> 24) & 0xff, (addr >> 16) & 0xff,</div>

<div>-                      (addr >> 8) & 0xff, addr & 0xff);</div></div><div class="im"><div>+                      "unexpected response for %s", text);</div><div>         goto failed;</div><div>
     }</div><div><br></div>
</div><div>@@ -1636,12 +1749,15 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,</div><div class="im"><div><br></div><div>     if (ident != qident) {</div><div>         ngx_log_error(r->log_level, r->log, 0,</div>
<div>
-                    "wrong ident %ui response for %ud.%ud.%ud.%ud, expect %ui",</div><div>-                    ident, (addr >> 24) & 0xff, (addr >> 16) & 0xff,</div><div>-                    (addr >> 8) & 0xff, addr & 0xff, qident);</div>

<div>+                    "wrong ident %ui response for %s, expect %ui",</div><div>+                    ident, text, qident);</div><div>         goto failed;</div><div>     }</div><div><br></div><div>+    ngx_log_error(r->log_level, r->log, 0,</div>

<div>+                "code: %d, nan: %d",</div><div>+                code, nan);</div><div>+</div></div><div class="im"><div>     if (code == 0 && nan == 0) {</div></div><div class="im"><div>         code = 3; /* NXDOMAIN */</div>
<div>     }</div>
</div><div>@@ -1669,8 +1785,6 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,</div><div class="im"><div>         return;</div><div>     }</div><div><br></div><div>-    i += sizeof("\7in-addr\4arpa") + sizeof(ngx_resolver_qs_t);</div>

<div>-</div><div>     if (i + 2 + sizeof(ngx_resolver_an_t) > (ngx_uint_t) n) {</div><div>         goto short_response;</div><div>     }</div></div><div>@@ -1750,10 +1864,10 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,</div>

<div><br></div><div>     return;</div><div><div class="im"><div>-invalid_in_addr_arpa:</div><div>+invalid_arpa:</div><div><br></div><div>     ngx_log_error(r->log_level, r->log, 0,</div><div>-                  "invalid in-addr.arpa name in DNS response");</div>

<div>+                  "invalid in-addr.arpa or ip6.arpa name in DNS response");</div><div>     return;</div><div><br></div><div> short_response:</div></div><div>@@ -1818,28 +1932,54 @@ ngx_resolver_lookup_name(ngx_resolver_t *r, ngx_str_t *name, uint32_t hash)</div>
<div><div class="h5">
<div><br></div><div><br></div><div> static ngx_resolver_node_t *</div><div>-ngx_resolver_lookup_addr(ngx_resolver_t *r, in_addr_t addr)</div><div>+ngx_resolver_lookup_addr(ngx_resolver_t *r, ngx_ipaddr_t addr, uint32_t hash)</div>

<div> {</div><div>+    ngx_int_t             rc;</div><div>     ngx_rbtree_node_t  *node, *sentinel;</div><div>+    ngx_resolver_node_t  *rn;</div><div><br></div><div>     node = r->addr_rbtree.root;</div><div>     sentinel = r->addr_rbtree.sentinel;</div>

<div><br></div><div>     while (node != sentinel) {</div><div><br></div><div>-        if (addr < node->key) {</div><div>+        if (hash < node->key) {</div><div>             node = node->left;</div><div>
             continue;</div>
<div>         }</div><div><br></div><div>-        if (addr > node->key) {</div><div>+        if (hash > node->key) {</div><div>             node = node->right;</div><div>             continue;</div><div>         }</div>

<div><br></div><div>-        /* addr == node->key */</div><div>+        /* hash == node->key */</div><div>+</div><div>+        rn = (ngx_resolver_node_t *) node;</div><div>+</div><div>+        rc = addr.family - rn->u.addr.family;</div>

</div></div></div></div><div><div><div class="h5"><div>+</div><div>+        if (rc == 0) {</div><div>+</div><div>+            switch (addr.family) {</div><div>+            case AF_INET:</div><div>+                rc = ngx_memn2cmp((u_char *)&addr.u.v4, (u_char *)&rn->u.addr.u.v4, sizeof(in_addr_t), sizeof(in_addr_t));</div>

<div>+                break;</div><div>+</div><div>+#if (NGX_HAVE_INET6)</div><div>+            case AF_INET6:</div><div>+                rc = ngx_memn2cmp((u_char *)&addr.u.v6, (u_char *)&rn->u.addr.u.v6, sizeof(struct in6_addr), sizeof(struct in6_addr));</div>

<div>+                break;</div></div></div><div>+#endif</div><div>+            }</div><div>+</div><div class="im"><div>+            if (rc == 0) {</div><div>+                return rn;</div><div>+            }</div><div>
<br></div></div><div class="im"><div>-        return (ngx_resolver_node_t *) node;</div>
<div>+        }</div><div>+</div><div>+        node = (rc < 0) ? node->left : node->right;</div><div>     }</div><div><br></div><div>     /* not found */</div></div><div>@@ -1854,6 +1994,7 @@ ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp,</div>
<div class="im">
<div> {</div><div>     ngx_rbtree_node_t    **p;</div><div>     ngx_resolver_node_t   *rn, *rn_temp;</div><div>+    ngx_int_t              rc;</div><div><br></div><div>     for ( ;; ) {</div><div><br></div></div><div>@@ -1870,8 +2011,29 @@ ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp,</div>
<div><div class="h5">
<div>             rn = (ngx_resolver_node_t *) node;</div><div>             rn_temp = (ngx_resolver_node_t *) temp;</div><div><br></div><div>-            p = (ngx_memn2cmp(rn->name, rn_temp->name, rn->nlen, rn_temp->nlen)</div>

<div>-                 < 0) ? &temp->left : &temp->right;</div><div>+            if (rn->qtype == NGX_RESOLVE_PTR) {</div><div>+                rc = rn->u.addr.family - rn_temp->u.addr.family;</div>

<div>+</div></div></div></div><div><div><div class="h5"><div>+                if (rc == 0) {</div><div>+</div><div>+                    switch (rn->u.addr.family) {</div><div>+                    case AF_INET:</div><div>
+                        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));</div>
<div>+                        break;</div><div>+</div><div>+        #if (NGX_HAVE_INET6)</div><div>+                    case AF_INET6:</div><div>+                        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));</div>

<div>+                        break;</div><div>+        #endif</div><div>+                    }</div><div>+                }</div><div>+</div><div>+            } else {</div><div>+                rc = ngx_memn2cmp(rn->name, rn_temp->name, rn->nlen, rn_temp->nlen);</div>

<div>+            }</div><div>+</div><div>+            p = (rc < 0) ? &temp->left : &temp->right;</div><div>         }</div><div><br></div><div>         if (*p == sentinel) {</div></div></div><div>@@ -1989,8 +2151,6 @@ ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)</div>
<div class="im">
<div> }</div><div><br></div><div><br></div><div>-/* AF_INET only */</div><div>-</div><div> static ngx_int_t</div><div> ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)</div><div> {</div></div>
<div>
@@ -2001,7 +2161,7 @@ ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)</div><div class="im"><div>     ngx_resolver_query_t  *query;</div><div><br></div><div>     len = sizeof(ngx_resolver_query_t)</div>
<div>
-          + sizeof(".255.255.255.255.in-addr.arpa.") - 1</div><div>+          + NGX_PTR_QUERY_LEN</div><div>           + sizeof(ngx_resolver_qs_t);</div><div><br></div><div>     p = ngx_resolver_alloc(ctx->resolver, len);</div>

</div><div>@@ -2028,18 +2188,50 @@ ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)</div><div><div class="h5"><div><div>     p += sizeof(ngx_resolver_query_t);</div><div><br></div><div>-    for (n = 0; n < 32; n += 8) {</div>

<div>-        d = ngx_sprintf(&p[1], "%ud", (ctx->addr >> n) & 0xff);</div><div>-        *p = (u_char) (d - &p[1]);</div><div>-        p = d;</div><div>+    switch (ctx->addr.family) {</div>

<div>+</div><div>+    case AF_INET:</div><div>+        for (n = 0; n < 32; n += 8) {</div><div>+            d = ngx_sprintf(&p[1], "%ud", (ctx->addr.u.v4 >> n) & 0xff);</div><div>+            *p = (u_char) (d - &p[1]);</div>

<div>+            p = d;</div><div>+        }</div><div>+</div><div>+        /* query type "PTR", IP query class */</div><div>+        ngx_memcpy(p, "\7in-addr\4arpa\0\0\14\0\1", 18);</div><div>+</div>

<div>+        rn->qlen = (u_short)</div><div>+                      (p + sizeof("\7in-addr\4arpa") + sizeof(ngx_resolver_qs_t)</div><div>+                       - rn->query);</div><div>+</div><div>+        break;</div>

<div>+</div><div>+#if (NGX_HAVE_INET6)</div><div>+    case AF_INET6:</div><div>+        for (n = 15; n >= 0; n--) {</div><div>+            p = ngx_sprintf(p, "\1%xd\1%xd",</div><div>+                            (ctx->addr.u.v6.s6_addr[n]) & 0xf,</div>

<div>+                            (ctx->addr.u.v6.s6_addr[n] >> 4) & 0xf);</div><div>+</div><div>+        }</div><div>+</div><div>+        /* query type "PTR", IP query class */</div><div>+        ngx_memcpy(p, "\3ip6\4arpa\0\0\14\0\1", 18);</div>

<div>+</div><div>+        rn->qlen = (u_short)</div><div>+                      (p + sizeof("\3ip6\4arpa") + sizeof(ngx_resolver_qs_t)</div><div>+                       - rn->query);</div><div>+</div><div>

+        break;</div><div>+#endif</div><div>+</div></div></div></div></div><div><div><div class="h5"><div>+    default:</div><div>+        return NGX_ERROR;</div><div>     }</div><div><br></div><div>-    /* query type "PTR", IP query class */</div>

<div>-    ngx_memcpy(p, "\7in-addr\4arpa\0\0\14\0\1", 18);</div><div>+ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0,</div><div>+               "resolve: query %s, ident %i", (rn->query+12), ident & 0xffff);</div>

<div><br></div><div>-    rn->qlen = (u_short)</div><div>-                  (p + sizeof("\7in-addr\4arpa") + sizeof(ngx_resolver_qs_t)</div><div>-                   - rn->query);</div><div><br></div><div>     return NGX_OK;</div>

<div> }</div></div></div><div>diff --git a/src/core/ngx_resolver.h b/src/core/ngx_resolver.h</div><div>index d2a4606..a45b244 100644</div><div>--- a/src/core/ngx_resolver.h</div><div>+++ b/src/core/ngx_resolver.h</div><div>
@@ -41,6 +41,11 @@</div><div class="im">
<div><br></div><div> #define NGX_RESOLVER_MAX_RECURSION    50</div><div><br></div><div>+#if (NGX_HAVE_INET6)</div><div>+#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)</div>

<div>+#else</div><div>+#define NGX_PTR_QUERY_LEN   (sizeof(".255.255.255.255.in-addr.arpa.") - 1)</div><div>+#endif</div><div><br></div><div> typedef struct {</div><div>     ngx_connection_t         *connection;</div>

</div></div><div><br></div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Jul 10, 2013 at 9:24 PM, ToSHiC <span dir="ltr"><<a href="mailto:toshic.toshic@gmail.com" target="_blank">toshic.toshic@gmail.com</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>commit 8670b164784032b2911b3c34ac31ef52ddba5b60</div><div>Author: Anton Kortunov <<a href="mailto:toshic.toshic@gmail.com" target="_blank">toshic.toshic@gmail.com</a>></div>

<div>Date:   Wed Jul 10 19:53:06 2013 +0400</div>
<div><br></div><div>    IPv6 support in resolver for forward requests</div><div><br></div><div>    To resolve name into IPv6 address use NGX_RESOLVE_AAAA,</div><div>    NGX_RESOLVE_A_AAAA or NGX_RESOLVE_AAAA_A record type instead of</div>


<div>    NGX_RESOLVE_A</div><div><br></div><div>diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c</div><div>index d59d0c4..567368b 100644</div><div>--- a/src/core/ngx_resolver.c</div><div>+++ b/src/core/ngx_resolver.c</div>


<div>@@ -76,7 +76,7 @@ static void ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,</div><div><div><div> static ngx_resolver_node_t *ngx_resolver_lookup_name(ngx_resolver_t *r,</div><div>     ngx_str_t *name, uint32_t hash);</div>


<div> static ngx_resolver_node_t *ngx_resolver_lookup_addr(ngx_resolver_t *r,</div><div>-    in_addr_t addr);</div><div>+    ngx_ipaddr_t addr, uint32_t hash);</div><div> static void ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp,</div>


<div>     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);</div><div> static ngx_int_t ngx_resolver_copy(ngx_resolver_t *r, ngx_str_t *name,</div><div>@@ -88,7 +88,7 @@ static void *ngx_resolver_calloc(ngx_resolver_t *r, size_t size);</div>


<div> static void ngx_resolver_free(ngx_resolver_t *r, void *p);</div><div> static void ngx_resolver_free_locked(ngx_resolver_t *r, void *p);</div><div> static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size);</div>


<div>-static in_addr_t *ngx_resolver_rotate(ngx_resolver_t *r, in_addr_t *src,</div><div>+static ngx_ipaddr_t *ngx_resolver_rotate(ngx_resolver_t *r, ngx_ipaddr_t *src,</div><div>     ngx_uint_t n);</div><div> static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len);</div>


<div><br></div><div>@@ -270,13 +270,27 @@ ngx_resolver_cleanup_tree(ngx_resolver_t *r, ngx_rbtree_t *tree)</div><div> ngx_resolver_ctx_t *</div><div> ngx_resolve_start(ngx_resolver_t *r, ngx_resolver_ctx_t *temp)</div><div>


 {</div><div>-    in_addr_t            addr;</div><div>+    ngx_ipaddr_t         addr;</div><div>     ngx_resolver_ctx_t  *ctx;</div><div><br></div><div>     if (temp) {</div><div>-        addr = ngx_inet_addr(temp->name.data, temp->name.len);</div>


<div>+        addr.family = 0;</div><div><div><br></div><div>-        if (addr != INADDR_NONE) {</div><div>+</div><div>+        addr.u.v4 = ngx_inet_addr(temp->name.data, temp->name.len);</div><div>+</div><div>+        if (addr.u.v4 != INADDR_NONE) {</div>


<div>+</div><div>+            addr.family = AF_INET;</div><div>+</div><div>+#if (NGX_HAVE_INET6)</div><div>+        } else if (ngx_inet6_addr(temp->name.data, temp->name.len, addr.u.v6.s6_addr) == NGX_OK) {</div><div>


+</div><div>+            addr.family = AF_INET6;</div><div>+#endif</div><div>+        }</div><div>+</div><div>+        if (addr.family) {</div><div>             temp->resolver = r;</div><div>             temp->state = NGX_OK;</div>


<div>             temp->naddrs = 1;</div><div>@@ -417,7 +431,7 @@ static ngx_int_t</div><div> ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)</div><div> {</div><div>     uint32_t              hash;</div>


<div>-    in_addr_t             addr, *addrs;</div><div>+    ngx_ipaddr_t          addr, *addrs;</div><div>     ngx_int_t             rc;</div><div>     ngx_uint_t            naddrs;</div><div>     ngx_resolver_ctx_t   *next;</div>


<div>@@ -429,7 +443,11 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)</div><div><br></div><div>     if (rn) {</div><div><br></div><div>-        if (rn->valid >= ngx_time()) {</div><div>+        if (rn->valid >= ngx_time()</div>


<div>+#if (NGX_HAVE_INET6)</div><div>+ && rn->qtype != NGX_RESOLVE_RETRY</div><div>+#endif</div><div>+                                    ) {</div><div><br></div><div>             ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0, "resolve cached");</div>


<div><br></div><div>@@ -446,7 +464,6 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)</div></div></div></div><div><div><div><div>                 /* NGX_RESOLVE_A answer */</div><div><br>
</div><div>                 if (naddrs != 1) {</div>
<div>-                    addr = 0;</div><div>                     addrs = ngx_resolver_rotate(r, rn->u.addrs, naddrs);</div><div>                     if (addrs == NULL) {</div><div>                         return NGX_ERROR;</div>


<div>@@ -506,6 +523,8 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)</div><div>             } while (ctx);</div><div><br></div><div>             return NGX_OK;</div><div>+        } else {</div><div>


+            rn->qtype = ctx->type;</div><div>         }</div><div><br></div><div>         if (rn->waiting) {</div><div>@@ -552,6 +571,7 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)</div>


<div>         rn->node.key = hash;</div><div>         rn->nlen = (u_short) ctx->name.len;</div><div>         rn->query = NULL;</div><div>+        rn->qtype = ctx->type;</div><div><br></div><div>         ngx_rbtree_insert(&r->name_rbtree, &rn->node);</div>


<div>     }</div></div></div><div>@@ -1130,6 +1150,9 @@ found:</div><div><div>     switch (qtype) {</div><div><br></div><div>     case NGX_RESOLVE_A:</div><div>+#if (NGX_HAVE_INET6)</div><div>+    case NGX_RESOLVE_AAAA:</div>

<div>+#endif</div>
<div><br></div><div>         ngx_resolver_process_a(r, buf, n, ident, code, nan,</div><div>                                i + sizeof(ngx_resolver_qs_t));</div></div><div>@@ -1178,7 +1201,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,</div>

<div>
<div>     size_t                len;</div><div>     int32_t               ttl;</div><div>     uint32_t              hash;</div><div>-    in_addr_t             addr, *addrs;</div><div>+    ngx_ipaddr_t          addr, *addrs;</div>


<div>     ngx_str_t             name;</div><div>     ngx_uint_t            qtype, qident, naddrs, a, i, n, start;</div><div>     ngx_resolver_an_t    *an;</div></div></div><div><div>@@ -1212,12 +1235,57 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,</div>

<div>
<div>         goto failed;</div><div>     }</div><div><br></div><div>-    ngx_resolver_free(r, name.data);</div><div>-</div><div>     if (code == 0 && nan == 0) {</div><div>+</div><div>+#if (NGX_HAVE_INET6)</div>

</div><div>
+       /*</div><div>+     * If it was required dual type v4|v6 resolv create one more request</div><div>+     */</div><div><div><div>+       if (rn->qtype == NGX_RESOLVE_A_AAAA</div><div>+               || rn->qtype == NGX_RESOLVE_AAAA_A) {</div>


<div>+</div><div>+            ngx_queue_remove(&rn->queue);</div><div>+</div><div>+            rn->valid = ngx_time() + (r->valid ? r->valid : ttl);</div><div>+            rn->expire = ngx_time() + r->expire;</div>


<div>+</div><div>+            ngx_queue_insert_head(&r->name_expire_queue, &rn->queue);</div><div>+</div><div>+            ctx = rn->waiting;</div><div>+            rn->waiting = NULL;</div><div>+</div>


<div>+            if (ctx) {</div><div>+                ctx->name = name;</div><div>+</div><div>+                switch (rn->qtype) {</div><div>+</div><div>+                case NGX_RESOLVE_A_AAAA:</div><div>+                    ctx->type = NGX_RESOLVE_AAAA;</div>


<div>+                    break;</div><div>+</div><div>+                case NGX_RESOLVE_AAAA_A:</div><div>+                    ctx->type = NGX_RESOLVE_A;</div><div>+                    break;</div><div>+                }</div>


<div>+</div><div>+                ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,</div><div>+                              "restarting request for name %V, with type %ud",</div><div>+                              &name, ctx->type);</div>


<div>+</div></div></div></div><div><div><div><div>+                rn->qtype = NGX_RESOLVE_RETRY;</div><div>+</div><div>+                (void) ngx_resolve_name_locked(r, ctx);</div><div>+            }</div>
<div>+</div><div>+            return;</div>
<div>+        }</div><div>+#endif</div><div>+</div><div>         code = 3; /* NXDOMAIN */</div><div>     }</div><div><br></div><div>+    ngx_resolver_free(r, name.data);</div><div>+</div><div>     if (code) {</div><div>         next = rn->waiting;</div>


<div>         rn->waiting = NULL;</div></div></div><div>@@ -1243,7 +1311,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,</div><div><div><br></div><div>     i = ans;</div><div>     naddrs = 0;</div>

<div>-    addr = 0;</div>
<div>+    addr.family = 0;</div><div>     addrs = NULL;</div><div>     cname = NULL;</div><div>     qtype = 0;</div></div><div>@@ -1302,13 +1370,30 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,</div>

<div><div><div>
                 goto short_response;</div><div>             }</div><div><br></div><div>-            addr = htonl((buf[i] << 24) + (buf[i + 1] << 16)</div><div>+            addr.family = AF_INET;</div><div>+            addr.u.v4 = htonl((buf[i] << 24) + (buf[i + 1] << 16)</div>


<div>                          + (buf[i + 2] << 8) + (buf[i + 3]));</div><div><br></div><div>             naddrs++;</div><div><br></div><div>             i += len;</div><div><br></div><div>+#if (NGX_HAVE_INET6)</div>


<div>+        } else if (qtype == NGX_RESOLVE_AAAA) {</div><div>+</div><div>+            i += sizeof(ngx_resolver_an_t);</div></div></div></div><div><div><div><div>+</div><div>+            if (i + len > last) {</div>
<div>+                goto short_response;</div>
<div>+            }</div><div>+</div><div>+            addr.family = AF_INET6;</div><div>+            ngx_memcpy(&addr.u.v6.s6_addr, &buf[i], 16);</div><div>+</div><div>+            naddrs++;</div><div>+</div><div>


+            i += len;</div><div>+#endif</div><div>         } else if (qtype == NGX_RESOLVE_CNAME) {</div><div>             cname = &buf[i] + sizeof(ngx_resolver_an_t);</div><div>             i += sizeof(ngx_resolver_an_t) + len;</div>


</div></div><div>@@ -1333,7 +1418,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,</div><div><div><br></div><div>         } else {</div><div><br></div><div>-            addrs = ngx_resolver_alloc(r, naddrs * sizeof(in_addr_t));</div>


<div>+            addrs = ngx_resolver_alloc(r, naddrs * sizeof(ngx_ipaddr_t));</div><div>             if (addrs == NULL) {</div><div>                 return;</div><div>             }</div></div><div>@@ -1369,12 +1454,23 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,</div>

<div>
<div><br></div><div>                 if (qtype == NGX_RESOLVE_A) {</div><div><br></div><div>-                    addrs[n++] = htonl((buf[i] << 24) + (buf[i + 1] << 16)</div><div>+                    addrs[n].family = AF_INET;</div>


<div>+                    addrs[n++].u.v4 = htonl((buf[i] << 24) + (buf[i + 1] << 16)</div><div>                                        + (buf[i + 2] << 8) + (buf[i + 3]));</div><div><br></div><div>                     if (n == naddrs) {</div>


<div>                         break;</div><div>                     }</div><div>+#if (NGX_HAVE_INET6)</div><div>+                } else if (qtype == NGX_RESOLVE_AAAA) {</div><div>+</div><div>+                    addrs[n].family = AF_INET6;</div>


<div>+                    ngx_memcpy(&addrs[n++].u.v6.s6_addr, &buf[i], 16);</div><div>+</div><div>+                    if (n == naddrs) {</div></div></div><div><div><div>+                        break;</div>
<div>+                    }</div>
<div>+#endif</div><div>                 }</div><div><br></div><div>                 i += len;</div></div><div>@@ -1383,7 +1479,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,</div><div>
<div>             rn->u.addrs = addrs;</div>
<div><br></div><div>             addrs = ngx_resolver_dup(r, rn->u.addrs,</div><div>-                                     naddrs * sizeof(in_addr_t));</div><div>+                                     naddrs * sizeof(ngx_ipaddr_t));</div>


<div>             if (addrs == NULL) {</div><div>                 return;</div><div>             }</div></div><div>@@ -1838,7 +1934,20 @@ ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)</div>

<div><div>
     qs = (ngx_resolver_qs_t *) p;</div><div><br></div><div>     /* query type */</div><div>-    qs->type_hi = 0; qs->type_lo = (u_char) ctx->type;</div><div>+    qs->type_hi = 0; qs->type_lo = (u_char) rn->qtype;</div>


<div>+</div><div>+#if (NGX_HAVE_INET6)</div><div>+    switch (rn->qtype) {</div><div>+</div><div>+    case NGX_RESOLVE_A_AAAA:</div><div>+        qs->type_lo = NGX_RESOLVE_A;</div><div>+        break;</div><div>+</div>


<div>+    case NGX_RESOLVE_AAAA_A:</div><div>+        qs->type_lo = NGX_RESOLVE_AAAA;</div><div>+        break;</div><div>+    }</div><div>+#endif</div><div><br></div><div>     /* IP query class */</div><div>     qs->class_hi = 0; qs->class_lo = 1;</div>


</div><div>@@ -2136,13 +2245,13 @@ ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size)</div><div><div> }</div><div><br></div><div><br></div><div>-static in_addr_t *</div><div>-ngx_resolver_rotate(ngx_resolver_t *r, in_addr_t *src, ngx_uint_t n)</div>


</div></div><div><div><div>+static ngx_ipaddr_t *</div><div>+ngx_resolver_rotate(ngx_resolver_t *r, ngx_ipaddr_t *src, ngx_uint_t n)</div><div> {</div><div>     void        *dst, *p;</div><div>     ngx_uint_t   j;</div>
<div><br></div>
<div>-    dst = ngx_resolver_alloc(r, n * sizeof(in_addr_t));</div><div>+    dst = ngx_resolver_alloc(r, n * sizeof(ngx_ipaddr_t));</div><div><br></div><div>     if (dst == NULL) {</div><div>         return dst;</div></div>

<div>
@@ -2151,12 +2260,12 @@ ngx_resolver_rotate(ngx_resolver_t *r, in_addr_t *src, ngx_uint_t n)</div><div><div>     j = ngx_random() % n;</div><div><br></div></div></div><div><div><div>     if (j == 0) {</div>
<div>-        ngx_memcpy(dst, src, n * sizeof(in_addr_t));</div>
<div>+        ngx_memcpy(dst, src, n * sizeof(ngx_ipaddr_t));</div><div>         return dst;</div><div>     }</div><div><br></div><div>-    p = ngx_cpymem(dst, &src[j], (n - j) * sizeof(in_addr_t));</div><div>-    ngx_memcpy(p, src, j * sizeof(in_addr_t));</div>


<div>+    p = ngx_cpymem(dst, &src[j], (n - j) * sizeof(ngx_ipaddr_t));</div><div>+    ngx_memcpy(p, src, j * sizeof(ngx_ipaddr_t));</div><div><br></div><div>     return dst;</div><div> }</div></div><div>diff --git a/src/core/ngx_resolver.h b/src/core/ngx_resolver.h</div>


<div>index 6fd81fe..d2a4606 100644</div><div>--- a/src/core/ngx_resolver.h</div><div>+++ b/src/core/ngx_resolver.h</div><div>@@ -67,10 +67,11 @@ typedef struct {</div><div><div>     u_short                   qlen;</div>
<div><br>
</div><div>     u_char                   *query;</div><div>+    ngx_int_t                 qtype;</div><div><br></div><div>     union {</div><div>-        in_addr_t             addr;</div><div>-        in_addr_t            *addrs;</div>


<div>+        ngx_ipaddr_t          addr;</div><div>+        ngx_ipaddr_t         *addrs;</div><div>         u_char               *cname;</div><div>     } u;</div><div><br></div></div><div>@@ -130,8 +131,8 @@ struct ngx_resolver_ctx_s {</div>

<div>
<div>     ngx_str_t                 name;</div><div><br></div><div>     ngx_uint_t                naddrs;</div><div>-    in_addr_t                *addrs;</div><div>-    in_addr_t                 addr;</div><div>+    ngx_ipaddr_t             *addrs;</div>


<div>+    ngx_ipaddr_t              addr;</div><div><br></div><div>     ngx_resolver_handler_pt   handler;</div><div>     void                     *data;</div></div></div><div><br></div></div><div class="gmail_extra"><br>

<div><div><br><div class="gmail_quote">
On Wed, Jul 10, 2013 at 9:17 PM, ToSHiC <span dir="ltr"><<a href="mailto:toshic.toshic@gmail.com" target="_blank">toshic.toshic@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


<div dir="ltr"><div>commit 482bd2a0b6240a2b26409b9c7924ad01c814f293</div><div>Author: Anton Kortunov <<a href="mailto:toshic.toshic@gmail.com" target="_blank">toshic.toshic@gmail.com</a>></div><div>Date:   Wed Jul 10 13:21:27 2013 +0400</div>



<div><br></div><div>    Added NGX_RESOLVE_* constants</div><div><br></div><div>    Module developers can decide how to resolve hosts relating to IPv6:</div><div><br></div><div>    NGX_RESOLVE_AAAA - try to resolve only to IPv6 address</div>



<div>    NGX_RESOLVE_AAAA_A - IPv6 is preferred (recommended by standards)</div><div>    NGX_RESOLVE_A_AAAA - IPv4 is preferred (better strategy nowadays)</div><div><br></div><div>diff --git a/src/core/ngx_resolver.h b/src/core/ngx_resolver.h</div>



<div>index ae34ca5..6fd81fe 100644</div><div><div>--- a/src/core/ngx_resolver.h</div><div>+++ b/src/core/ngx_resolver.h</div><div>@@ -20,6 +20,15 @@</div><div> #define NGX_RESOLVE_TXT       16</div><div> #define NGX_RESOLVE_DNAME     39</div>



<div><br></div><div>+#if (NGX_HAVE_INET6)</div><div>+</div><div>+#define NGX_RESOLVE_AAAA      28</div><div>+#define NGX_RESOLVE_A_AAAA    1000</div><div>+#define NGX_RESOLVE_AAAA_A    1001</div><div>+#define NGX_RESOLVE_RETRY     1002</div>



<div>+</div><div>+#endif</div><div>+</div><div> #define NGX_RESOLVE_FORMERR   1</div><div> #define NGX_RESOLVE_SERVFAIL  2</div><div> #define NGX_RESOLVE_NXDOMAIN  3</div><div><br></div></div></div><div><div>
<div class="gmail_extra"><br>
<br><div class="gmail_quote">On Wed, Jul 10, 2013 at 9:17 PM, ToSHiC <span dir="ltr"><<a href="mailto:toshic.toshic@gmail.com" target="_blank">toshic.toshic@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">



<div dir="ltr">Hello,<div><br></div><div>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.</div><div>
<br></div><div><div>commit 597d09e7ae9247c5466b18aa2ef3f5892e61b708</div><div>Author: Anton Kortunov <<a href="mailto:toshic.toshic@gmail.com" target="_blank">toshic.toshic@gmail.com</a>></div><div>Date:   Wed Jul 10 13:14:52 2013 +0400</div>




<div><br></div><div>    Added new structure ngx_ipaddr_t</div><div><br></div><div>    This structure contains family field</div><div>    and the union of ipv4/ipv6 structures in_addr_t and in6_addr.</div><div>
<div><br></div><div>
diff --git a/src/core/ngx_inet.h b/src/core/ngx_inet.h</div><div>index 6a5a368..077ed34 100644</div><div>--- a/src/core/ngx_inet.h</div><div>+++ b/src/core/ngx_inet.h</div><div>@@ -68,6 +68,16 @@ typedef struct {</div><div>




<br></div><div><br></div><div> typedef struct {</div><div>+    ngx_uint_t                family;</div><div>+    union {</div><div>+        in_addr_t             v4;</div><div>+#if (NGX_HAVE_INET6)</div><div>+        struct in6_addr       v6;</div>




<div>+#endif</div><div>+    } u;</div><div>+} ngx_ipaddr_t;</div><div>+</div><div>+typedef struct {</div><div>     struct sockaddr          *sockaddr;</div><div>     socklen_t                 socklen;</div><div>     ngx_str_t                 name;</div>




<div><br></div></div></div></div><div><div><div class="gmail_extra"><br><br><div class="gmail_quote">On Mon, Jun 17, 2013 at 7:30 PM, Maxim Dounin <span dir="ltr"><<a href="mailto:mdounin@mdounin.ru" target="_blank">mdounin@mdounin.ru</a>></span> wrote:<br>




<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hello!<br>
<div><br>
On Fri, Jun 14, 2013 at 09:44:46PM +0400, ToSHiC wrote:<br>
<br>
> Hello,<br>
><br>
> We needed this feature in our company, I found that it is in milestones of<br>
> version 1.5 but doesn't exist yet. So I've implemented it based in 1.3 code<br>
> and merged in current 1.5 code. When I wrote this code I mostly cared about<br>
> minimum intrusion into other parts of nginx.<br>
><br>
> IPv6 fallback logic is not a straightforward implementation of suggested by<br>
> RFC. RFC states that IPv6 resolving have priority over IPv4, and it's not<br>
> very good for Internet we have currently. With this patch you can specify<br>
> priority, and in upstream and mail modules I've set IPv4 as preferred<br>
> address family.<br>
><br>
> Patch is pretty big and I hope it'll not break mailing list or mail clients.<br>
<br>
</div>You may want to try to split the patch into smaller patches to<br>
simplify review.  See also some hints here:<br>
<br>
<a href="http://nginx.org/en/docs/contributing_changes.html" target="_blank">http://nginx.org/en/docs/contributing_changes.html</a><br>
<br>
Some quick comments below.<br>
<br>
[...]<br>
<div><br>
> -        addr = ntohl(ctx->addr);<br>
> +failed:<br>
> +<br>
> +        //addr = ntohl(ctx->addr);<br>
> +        inet_ntop(ctx->addr.family, &ctx->addr.u, text,<br>
> NGX_SOCKADDR_STRLEN);<br>
><br>
>          ngx_log_error(NGX_LOG_ALERT, r->log, 0,<br>
> -                      "could not cancel %ud.%ud.%ud.%ud resolving",<br>
> -                      (addr >> 24) & 0xff, (addr >> 16) & 0xff,<br>
> -                      (addr >> 8) & 0xff, addr & 0xff);<br>
> +                      "could not cancel %s resolving", text);<br>
<br>
</div>1. Don't use inet_ntop(), there is ngx_sock_ntop() instead.<br>
<br>
2. Don't use C++ style ("//") comments.<br>
<br>
3. If some data is only needed for debug logging, keep relevant<br>
calculations under #if (NGX_DEBUG).<br>
<br>
[...]<br>
<div><br>
> @@ -334,6 +362,7 @@<br>
> ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r,<br>
>              peers->peer[i].current_weight = 0;<br>
>              peers->peer[i].max_fails = 1;<br>
>              peers->peer[i].fail_timeout = 10;<br>
> +<br>
>          }<br>
>      }<br>
><br>
<br>
</div>Please avoid unrelated changes.<br>
<br>
[...]<br>
<span><font color="#888888"><br>
--<br>
Maxim Dounin<br>
<a href="http://nginx.org/en/donation.html" target="_blank">http://nginx.org/en/donation.html</a><br>
<br>
_______________________________________________<br>
nginx-devel mailing list<br>
<a href="mailto:nginx-devel@nginx.org" target="_blank">nginx-devel@nginx.org</a><br>
<a href="http://mailman.nginx.org/mailman/listinfo/nginx-devel" target="_blank">http://mailman.nginx.org/mailman/listinfo/nginx-devel</a><br>
</font></span></blockquote></div><br></div>
</div></div></blockquote></div><br></div>
</div></div></blockquote></div><br></div></div></div>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>