[nginx] Resolver: implemented IPv6 name to address resolving.

Ruslan Ermilov ru at nginx.com
Fri Dec 13 16:54:49 UTC 2013


details:   http://hg.nginx.org/nginx/rev/98876ce2a7fd
branches:  
changeset: 5477:98876ce2a7fd
user:      Ruslan Ermilov <ru at nginx.com>
date:      Mon Dec 09 10:53:28 2013 +0400
description:
Resolver: implemented IPv6 name to address resolving.

diffstat:

 src/core/ngx_resolver.c                |  487 ++++++++++++++++++++++++++++----
 src/core/ngx_resolver.h                |   18 +-
 src/event/ngx_event_openssl_stapling.c |    1 -
 src/http/ngx_http_upstream.c           |    1 -
 src/mail/ngx_mail_smtp_handler.c       |    1 -
 5 files changed, 439 insertions(+), 69 deletions(-)

diffs (truncated from 897 to 300 lines):

diff -r 950c9ed3e66f -r 98876ce2a7fd src/core/ngx_resolver.c
--- a/src/core/ngx_resolver.c	Fri Dec 06 14:30:28 2013 +0400
+++ b/src/core/ngx_resolver.c	Mon Dec 09 10:53:28 2013 +0400
@@ -70,7 +70,8 @@ static void ngx_resolver_read_response(n
 static void ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf,
     size_t n);
 static void ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
-    ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan, ngx_uint_t ans);
+    ngx_uint_t ident, ngx_uint_t code, ngx_uint_t qtype,
+    ngx_uint_t nan, ngx_uint_t ans);
 static void ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
     ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan);
 static ngx_resolver_node_t *ngx_resolver_lookup_name(ngx_resolver_t *r,
@@ -88,8 +89,8 @@ static void *ngx_resolver_calloc(ngx_res
 static void ngx_resolver_free(ngx_resolver_t *r, void *p);
 static void ngx_resolver_free_locked(ngx_resolver_t *r, void *p);
 static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size);
-static ngx_addr_t *ngx_resolver_export(ngx_resolver_t *r, in_addr_t *src,
-    ngx_uint_t n, ngx_uint_t rotate);
+static ngx_addr_t *ngx_resolver_export(ngx_resolver_t *r,
+    ngx_resolver_node_t *rn, ngx_uint_t rotate);
 static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len);
 
 #if (NGX_HAVE_INET6)
@@ -435,8 +436,6 @@ done:
 }
 
 
-/* NGX_RESOLVE_A only */
-
 static ngx_int_t
 ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
 {
@@ -463,17 +462,18 @@ ngx_resolve_name_locked(ngx_resolver_t *
 
             ngx_queue_insert_head(&r->name_expire_queue, &rn->queue);
 
-            naddrs = rn->naddrs;
+            naddrs = (rn->naddrs == (u_short) -1) ? 0 : rn->naddrs;
+#if (NGX_HAVE_INET6)
+            naddrs += (rn->naddrs6 == (u_short) -1) ? 0 : rn->naddrs6;
+#endif
 
             if (naddrs) {
 
-                /* NGX_RESOLVE_A answer */
-
-                if (naddrs == 1) {
+                if (naddrs == 1 && rn->naddrs == 1) {
                     addrs = NULL;
 
                 } else {
-                    addrs = ngx_resolver_export(r, rn->u.addrs, naddrs, 1);
+                    addrs = ngx_resolver_export(r, rn, 1);
                     if (addrs == NULL) {
                         return NGX_ERROR;
                     }
@@ -558,16 +558,25 @@ ngx_resolve_name_locked(ngx_resolver_t *
         if (rn->query) {
             ngx_resolver_free_locked(r, rn->query);
             rn->query = NULL;
+#if (NGX_HAVE_INET6)
+            rn->query6 = NULL;
+#endif
         }
 
         if (rn->cnlen) {
             ngx_resolver_free_locked(r, rn->u.cname);
         }
 
-        if (rn->naddrs > 1) {
+        if (rn->naddrs > 1 && rn->naddrs != (u_short) -1) {
             ngx_resolver_free_locked(r, rn->u.addrs);
         }
 
+#if (NGX_HAVE_INET6)
+        if (rn->naddrs6 > 1 && rn->naddrs6 != (u_short) -1) {
+            ngx_resolver_free_locked(r, rn->u6.addrs6);
+        }
+#endif
+
         /* unlock alloc mutex */
 
     } else {
@@ -586,6 +595,9 @@ ngx_resolve_name_locked(ngx_resolver_t *
         rn->node.key = hash;
         rn->nlen = (u_short) ctx->name.len;
         rn->query = NULL;
+#if (NGX_HAVE_INET6)
+        rn->query6 = NULL;
+#endif
 
         ngx_rbtree_insert(&r->name_rbtree, &rn->node);
     }
@@ -609,6 +621,11 @@ ngx_resolve_name_locked(ngx_resolver_t *
         return NGX_OK;
     }
 
+    rn->naddrs = (u_short) -1;
+#if (NGX_HAVE_INET6)
+    rn->naddrs6 = (u_short) -1;
+#endif
+
     if (ngx_resolver_send_query(r, rn) != NGX_OK) {
         goto failed;
     }
@@ -635,8 +652,8 @@ ngx_resolve_name_locked(ngx_resolver_t *
 
     ngx_queue_insert_head(&r->name_resend_queue, &rn->queue);
 
+    rn->code = 0;
     rn->cnlen = 0;
-    rn->naddrs = 0;
     rn->valid = 0;
     rn->waiting = ctx;
 
@@ -762,6 +779,9 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx
 
         ngx_resolver_free(r, rn->query);
         rn->query = NULL;
+#if (NGX_HAVE_INET6)
+        rn->query6 = NULL;
+#endif
 
     } else {
         rn = ngx_resolver_alloc(r, sizeof(ngx_resolver_node_t));
@@ -783,6 +803,9 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx
         }
 
         rn->query = NULL;
+#if (NGX_HAVE_INET6)
+        rn->query6 = NULL;
+#endif
 
         ngx_rbtree_insert(tree, &rn->node);
     }
@@ -791,6 +814,11 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx
         goto failed;
     }
 
+    rn->naddrs = (u_short) -1;
+#if (NGX_HAVE_INET6)
+    rn->naddrs6 = (u_short) -1;
+#endif
+
     if (ngx_resolver_send_query(r, rn) != NGX_OK) {
         goto failed;
     }
@@ -815,8 +843,8 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx
 
     ngx_queue_insert_head(resend_queue, &rn->queue);
 
+    rn->code = 0;
     rn->cnlen = 0;
-    rn->naddrs = 0;
     rn->name = NULL;
     rn->nlen = 0;
     rn->valid = 0;
@@ -1023,16 +1051,33 @@ ngx_resolver_send_query(ngx_resolver_t *
         uc->connection->read->resolver = 1;
     }
 
-    n = ngx_send(uc->connection, rn->query, rn->qlen);
-
-    if (n == -1) {
-        return NGX_ERROR;
+    if (rn->naddrs == (u_short) -1) {
+        n = ngx_send(uc->connection, rn->query, rn->qlen);
+
+        if (n == -1) {
+            return NGX_ERROR;
+        }
+
+        if ((size_t) n != (size_t) rn->qlen) {
+            ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete");
+            return NGX_ERROR;
+        }
     }
 
-    if ((size_t) n != (size_t) rn->qlen) {
-        ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete");
-        return NGX_ERROR;
+#if (NGX_HAVE_INET6)
+    if (rn->query6 && rn->naddrs6 == (u_short) -1) {
+        n = ngx_send(uc->connection, rn->query6, rn->qlen);
+
+        if (n == -1) {
+            return NGX_ERROR;
+        }
+
+        if ((size_t) n != (size_t) rn->qlen) {
+            ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete");
+            return NGX_ERROR;
+        }
     }
+#endif
 
     return NGX_OK;
 }
@@ -1174,6 +1219,9 @@ ngx_resolver_process_response(ngx_resolv
     char                 *err;
     ngx_uint_t            i, times, ident, qident, flags, code, nqs, nan,
                           qtype, qclass;
+#if (NGX_HAVE_INET6)
+    ngx_uint_t            qident6;
+#endif
     ngx_queue_t          *q;
     ngx_resolver_qs_t    *qs;
     ngx_resolver_hdr_t   *response;
@@ -1217,12 +1265,18 @@ ngx_resolver_process_response(ngx_resolv
             qident = (rn->query[0] << 8) + rn->query[1];
 
             if (qident == ident) {
-                ngx_log_error(r->log_level, r->log, 0,
-                              "DNS error (%ui: %s), query id:%ui, name:\"%*s\"",
-                              code, ngx_resolver_strerror(code), ident,
-                              rn->nlen, rn->name);
-                return;
+                goto dns_error_name;
             }
+
+#if (NGX_HAVE_INET6)
+            if (rn->query6) {
+                qident6 = (rn->query6[0] << 8) + rn->query6[1];
+
+                if (qident6 == ident) {
+                    goto dns_error_name;
+                }
+            }
+#endif
         }
 
         goto dns_error;
@@ -1279,8 +1333,11 @@ found:
     switch (qtype) {
 
     case NGX_RESOLVE_A:
-
-        ngx_resolver_process_a(r, buf, n, ident, code, nan,
+#if (NGX_HAVE_INET6)
+    case NGX_RESOLVE_AAAA:
+#endif
+
+        ngx_resolver_process_a(r, buf, n, ident, code, qtype, nan,
                                i + sizeof(ngx_resolver_qs_t));
 
         break;
@@ -1309,6 +1366,14 @@ done:
 
     return;
 
+dns_error_name:
+
+    ngx_log_error(r->log_level, r->log, 0,
+                  "DNS error (%ui: %s), query id:%ui, name:\"%*s\"",
+                  code, ngx_resolver_strerror(code), ident,
+                  rn->nlen, rn->name);
+    return;
+
 dns_error:
 
     ngx_log_error(r->log_level, r->log, 0,
@@ -1320,7 +1385,8 @@ dns_error:
 
 static void
 ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
-    ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan, ngx_uint_t ans)
+    ngx_uint_t ident, ngx_uint_t code, ngx_uint_t qtype,
+    ngx_uint_t nan, ngx_uint_t ans)
 {
     char                 *err;
     u_char               *cname;
@@ -1331,6 +1397,9 @@ ngx_resolver_process_a(ngx_resolver_t *r
     ngx_str_t             name;
     ngx_addr_t           *addrs;
     ngx_uint_t            type, class, qident, naddrs, a, i, n, start;
+#if (NGX_HAVE_INET6)
+    struct in6_addr      *addr6;
+#endif
     ngx_resolver_an_t    *an;
     ngx_resolver_ctx_t   *ctx, *next;
     ngx_resolver_node_t  *rn;
@@ -1350,14 +1419,43 @@ ngx_resolver_process_a(ngx_resolver_t *r
 
     rn = ngx_resolver_lookup_name(r, &name, hash);
 
-    if (rn == NULL || rn->query == NULL) {
+    if (rn == NULL) {
         ngx_log_error(r->log_level, r->log, 0,
                       "unexpected response for %V", &name);
         ngx_resolver_free(r, name.data);
         goto failed;
     }
 
-    qident = (rn->query[0] << 8) + rn->query[1];
+    switch (qtype) {
+
+#if (NGX_HAVE_INET6)
+    case NGX_RESOLVE_AAAA:
+



More information about the nginx-devel mailing list