<div dir="ltr"><div>commit f194edc7e351d3a487e9305935647f0587b65fca</div><div>Author: Anton Kortunov <<a href="mailto:toshic.toshic@gmail.com">toshic.toshic@gmail.com</a>></div><div>Date: Wed Jul 10 20:53:21 2013 +0400</div>
<div><br></div><div> IPv6 support in mail server</div><div><br></div><div> Client ip address is resolving to hostname even if it's IPv6 address.</div><div> Forward resolve of this hostname is processed according to socket family.</div>
<div><br></div><div>diff --git a/src/mail/ngx_mail_smtp_handler.c b/src/mail/ngx_mail_smtp_handler.c</div><div>index 2171423..481e4a4 100644</div><div>--- a/src/mail/ngx_mail_smtp_handler.c</div><div>+++ b/src/mail/ngx_mail_smtp_handler.c</div>
<div>@@ -56,6 +56,9 @@ void</div><div> ngx_mail_smtp_init_session(ngx_mail_session_t *s, ngx_connection_t *c)</div><div> {</div><div> struct sockaddr_in *sin;</div><div>+#if (NGX_HAVE_INET6)</div><div>+ struct sockaddr_in6 *sin6;</div>
<div>+#endif</div><div> ngx_resolver_ctx_t *ctx;</div><div> ngx_mail_core_srv_conf_t *cscf;</div><div><br></div><div>@@ -67,7 +70,11 @@ ngx_mail_smtp_init_session(ngx_mail_session_t *s, ngx_connection_t *c)</div>
<div> return;</div><div> }</div><div><br></div><div>- if (c->sockaddr->sa_family != AF_INET) {</div><div>+ if (c->sockaddr->sa_family != AF_INET</div><div>+#if (NGX_HAVE_INET6)</div><div>+ && c->sockaddr->sa_family != AF_INET6</div>
<div>+#endif</div><div>+ ) {</div><div> s->host = smtp_tempunavail;</div><div> ngx_mail_smtp_greeting(s, c);</div><div> return;</div><div>@@ -81,11 +88,23 @@ ngx_mail_smtp_init_session(ngx_mail_session_t *s, ngx_connection_t *c)</div>
<div> return;</div><div> }</div><div><br></div><div>- /* AF_INET only */</div><div>+ ctx->addr.family = c->sockaddr->sa_family;</div><div><div><br></div><div>- sin = (struct sockaddr_in *) c->sockaddr;</div>
<div>+ switch (c->sockaddr->sa_family) {</div><div>+</div><div>+ case AF_INET:</div><div>+ sin = (struct sockaddr_in *) c->sockaddr;</div><div>+ ctx->addr.u.v4 = sin->sin_addr.s_addr;</div>
<div>+ break;</div><div>+</div><div>+#if (NGX_HAVE_INET6)</div><div>+ case AF_INET6:</div><div>+ sin6 = (struct sockaddr_in6 *) c->sockaddr;</div><div>+ ctx->addr.u.v6 = sin6->sin6_addr;</div>
<div>+ break;</div><div>+#endif</div><div>+ }</div><div><br></div><div>- ctx->addr = sin->sin_addr.s_addr;</div><div> ctx->handler = ngx_mail_smtp_resolve_addr_handler;</div><div> ctx->data = s;</div>
<div> ctx->timeout = cscf->resolver_timeout;</div><div>@@ -167,11 +186,23 @@ ngx_mail_smtp_resolve_name(ngx_event_t *rev)</div><div> }</div><div><br></div><div> ctx->name = s->host;</div><div>- ctx->type = NGX_RESOLVE_A;</div>
<div> ctx->handler = ngx_mail_smtp_resolve_name_handler;</div><div> ctx->data = s;</div><div> ctx->timeout = cscf->resolver_timeout;</div><div><br></div><div>+ switch (c->sockaddr->sa_family) {</div>
<div>+</div><div>+ case AF_INET:</div><div>+ ctx->type = NGX_RESOLVE_A;</div><div>+ break;</div><div>+</div><div>+#if (NGX_HAVE_INET6)</div><div>+ case AF_INET6:</div><div>+ ctx->type = NGX_RESOLVE_AAAA_A;</div>
<div>+ break;</div><div>+#endif</div><div>+ }</div><div>+</div><div> if (ngx_resolve_name(ctx) != NGX_OK) {</div></div><div><div> ngx_mail_close_connection(c);</div><div> }</div><div>@@ -181,10 +212,13 @@ ngx_mail_smtp_resolve_name(ngx_event_t *rev)</div>
<div> static void</div><div> ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx)</div><div> {</div><div>- in_addr_t addr;</div><div>+ ngx_ipaddr_t addr;</div><div> ngx_uint_t i;</div>
<div> ngx_connection_t *c;</div><div> struct sockaddr_in *sin;</div><div>+#if (NGX_HAVE_INET6)</div><div>+ struct sockaddr_in6 *sin6;</div><div>+#endif</div><div> ngx_mail_session_t *s;</div><div><br></div>
<div> s = ctx->data;</div><div>@@ -205,23 +239,55 @@ ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx)</div><div><br></div><div> } else {</div><div><br></div><div>- /* AF_INET only */</div><div>
+ addr.family = c->sockaddr->sa_family;</div><div><br></div><div>- sin = (struct sockaddr_in *) c->sockaddr;</div><div>+ switch (c->sockaddr->sa_family) {</div><div>+</div><div>+ case AF_INET:</div>
<div>+ sin = (struct sockaddr_in *) c->sockaddr;</div><div>+ addr.u.v4 = sin->sin_addr.s_addr;</div><div>+ break;</div><div>+</div><div>+#if (NGX_HAVE_INET6)</div><div>+ case AF_INET6:</div>
<div>+ sin6 = (struct sockaddr_in6 *) c->sockaddr;</div><div>+ addr.u.v6 = sin6->sin6_addr;</div><div>+ break;</div><div>+#endif</div><div>+ }</div><div><br></div><div> for (i = 0; i < ctx->naddrs; i++) {</div>
<div><br></div><div>- addr = ctx->addrs[i];</div></div><div><div>+#if (NGX_DEBUG)</div><div>+ {</div><div>+ u_char text[NGX_SOCKADDR_STRLEN];</div><div>+</div><div>+ ngx_inet_ntop(ctx->addrs[i].family, &ctx->addrs[i].u, text, NGX_SOCKADDR_STRLEN);</div>
<div>+</div><div>+ ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,</div><div>+ "name was resolved to %s", text);</div><div>+ }</div><div>+#endif</div><div>
+</div><div>+ if (addr.family != ctx->addrs[i].family) {</div><div>+ continue;</div><div>+ }</div><div><br></div><div>- ngx_log_debug4(NGX_LOG_DEBUG_MAIL, c->log, 0,</div>
<div>- "name was resolved to %ud.%ud.%ud.%ud",</div><div>- (ntohl(addr) >> 24) & 0xff,</div><div>- (ntohl(addr) >> 16) & 0xff,</div>
<div>- (ntohl(addr) >> 8) & 0xff,</div><div>- ntohl(addr) & 0xff);</div><div>+ switch (addr.family) {</div><div><br></div><div>- if (addr == sin->sin_addr.s_addr) {</div>
<div>- goto found;</div><div>+ case AF_INET:</div><div>+ if (addr.u.v4 == ctx->addrs[i].u.v4) {</div><div>+ goto found;</div><div>+ }</div><div>
+ break;</div><div>+</div><div>+#if (NGX_HAVE_INET6)</div><div>+ case AF_INET6:</div><div>+ if (!ngx_memcmp(&addr.u.v6, &ctx->addrs[i].u.v6, sizeof(addr.u.v6))) {</div><div>
+ goto found;</div><div>+ }</div><div>+ break;</div><div>+#endif</div><div> }</div><div> }</div><div><br></div></div></div><div class="gmail_extra"><br>
<br><div class="gmail_quote">On Wed, Jul 10, 2013 at 9:30 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 2bf37859004e3ff2b5dd9a11e1725153ca43ff32</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: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 class="im"><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><div>+ u_char text[NGX_SOCKADDR_STRLEN];</div><div class="im"><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><div>+ ngx_inet_ntop(ur->addrs[i].family, &ur->addrs[i].u, text, NGX_SOCKADDR_STRLEN);</div>
<div class="im"><div><br>
</div><div>- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,</div></div><div>- "name was resolved to %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>+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,</div><div>+ "name was resolved to %s", text);</div>
</div><div><div class="im"><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><div class="im"><div> ngx_uint_t naddrs;</div>
<div>- in_addr_t *addrs;</div></div><div>+ ngx_ipaddr_t *addrs;</div><div class="im"><div><br></div><div> struct sockaddr *sockaddr;</div><div> socklen_t socklen;</div>
</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 class="im"><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><div class="im"><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><div>+ case AF_INET:</div><div class="im"><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><div class="im"><div>+ break;</div>
<div>+</div>
<div>+#if (NGX_HAVE_INET6)</div><div>+ case AF_INET6:</div></div><div class="im"><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><div class="im"><div>+ break;</div>
<div>+#endif</div>
<div>+</div><div>+ default:</div></div><div class="im"><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 class="im"><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><div class="HOEnZb"><div class="h5">
<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><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><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>
<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>
<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><div>- ctx->addr = ntohl(ctx->addr);</div>
</div><div><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><div> goto failed;</div><div> }</div><div><br></div><div>- rn->node.key = ctx->addr;</div></div>
<div>+ rn->node.key = hash;</div><div>
<div> rn->query = NULL;</div><div>+ rn->qtype = ctx->type;</div></div><div><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><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><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><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>
<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><div> ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,</div></div><div><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><div>
- in_addr_t addr;</div>
<div>+ ngx_ipaddr_t addr;</div></div><div><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>
<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><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><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><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>
<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><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><div>+ /* Try to parse request as ip6.arpa */</div></div><div>+ addr.family = AF_INET6;</div>
<div><div>
<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><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><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><div>- (addr >> 24) & 0xff, (addr >> 16) & 0xff,</div>
<div>- (addr >> 8) & 0xff, addr & 0xff);</div></div><div><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><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><div> if (code == 0 && nan == 0) {</div></div><div><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><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><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>
<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><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><div>+ if (rc == 0) {</div><div>+ return rn;</div><div>+ }</div><div>
<br></div></div><div><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>
<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>
<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><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>
<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><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><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><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>
<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><div><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>
</div></div></blockquote></div><br></div>