[PATCH] Fix ptr resolving with cname

Ruslan Ermilov ru at nginx.com
Fri Dec 25 07:57:25 UTC 2015


On Wed, Dec 16, 2015 at 11:59:29AM +0800, DannyAAM wrote:
> # HG changeset patch
> # User DannyAAM <danny at saru.moe>
> # Date 1449696194 -28800
> #      Thu Dec 10 05:23:14 2015 +0800
> # Branch fix-ptr-cname
> # Node ID 9d8c7332b7300908414e3bec78a90d9d14b30af8
> # Parent  dfe68c41f34f865bc7b45cbe6b7d0f639de283fc
> Fix ptr resolving with cname
> 
> Make ptr process aware of cname & follow it.
> (This depends on resolver's recursive answer.)

Please try these patches instead.

# HG changeset patch
# User Ruslan Ermilov <ru at nginx.com>
# Date 1450362072 -10800
#      Thu Dec 17 17:21:12 2015 +0300
# Node ID 799f1ad5e2f31d50ec1200f9c210c6763e3ece37
# Parent  78b4e10b4367b31367aad3c83c9c3acdd42397c4
Resolver: style.

Renamed argument in ngx_resolver_process_a() and ngx_resolver_process_ptr(),
for consistency.

diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -75,11 +75,11 @@ static ngx_uint_t ngx_resolver_resend_em
 static void ngx_resolver_read_response(ngx_event_t *rev);
 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 qtype,
+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 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 void ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf,
+    size_t last, ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan);
 static ngx_resolver_node_t *ngx_resolver_lookup_name(ngx_resolver_t *r,
     ngx_str_t *name, uint32_t hash);
 static ngx_resolver_node_t *ngx_resolver_lookup_addr(ngx_resolver_t *r,
@@ -2022,7 +2022,7 @@ next:
 
 
 static void
-ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
+ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t last,
     ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan)
 {
     char                 *err;
@@ -2045,7 +2045,7 @@ ngx_resolver_process_ptr(ngx_resolver_t 
 #endif
 
     if (ngx_resolver_copy(r, NULL, buf,
-                          buf + sizeof(ngx_resolver_hdr_t), buf + n)
+                          buf + sizeof(ngx_resolver_hdr_t), buf + last)
         != NGX_OK)
     {
         return;
@@ -2185,7 +2185,7 @@ valid:
 
     i += sizeof(ngx_resolver_qs_t);
 
-    if (i + 2 + sizeof(ngx_resolver_an_t) >= n) {
+    if (i + 2 + sizeof(ngx_resolver_an_t) >= last) {
         goto short_response;
     }
 
@@ -2220,11 +2220,11 @@ valid:
 
     i += 2 + sizeof(ngx_resolver_an_t);
 
-    if (i + len > n) {
+    if (i + len > last) {
         goto short_response;
     }
 
-    if (ngx_resolver_copy(r, &name, buf, buf + i, buf + n) != NGX_OK) {
+    if (ngx_resolver_copy(r, &name, buf, buf + i, buf + last) != NGX_OK) {
         goto failed;
     }
 
# HG changeset patch
# User Ruslan Ermilov <ru at nginx.com>
# Date 1450362076 -10800
#      Thu Dec 17 17:21:16 2015 +0300
# Node ID 35f2e54f88cd582b8ab5ad617022022e0bcf8acd
# Parent  799f1ad5e2f31d50ec1200f9c210c6763e3ece37
Resolver: improved PTR response processing.

The previous code only parsed the first answer, without checking its
type, and requiring a compressed RR name.

The new code checks the RR type, supports responses with multiple
answers, and doesn't require the RR name to be compressed.

This has a side effect in limited support of CNAME.  If a response
includes both CNAME and PTR RRs, like when recursion is enabled on
the server, PTR RR is handled.

Full CNAME support in PTR response is not implemented in this change.

diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -2032,7 +2032,7 @@ ngx_resolver_process_ptr(ngx_resolver_t 
     int32_t               ttl;
     ngx_int_t             octet;
     ngx_str_t             name;
-    ngx_uint_t            i, mask, qident, class;
+    ngx_uint_t            mask, type, class, qident, a, i, start;
     ngx_queue_t          *expire_queue;
     ngx_rbtree_t         *tree;
     ngx_resolver_an_t    *an;
@@ -2185,44 +2185,96 @@ valid:
 
     i += sizeof(ngx_resolver_qs_t);
 
-    if (i + 2 + sizeof(ngx_resolver_an_t) >= last) {
+    for (a = 0; a < nan; a++) {
+
+        start = i;
+
+        while (i < last) {
+
+            if (buf[i] & 0xc0) {
+                i += 2;
+                goto found;
+            }
+
+            if (buf[i] == 0) {
+                i++;
+                goto test_length;
+            }
+
+            i += 1 + buf[i];
+        }
+
         goto short_response;
+
+    test_length:
+
+        if (i - start < 2) {
+            err = "invalid name in DNS response";
+            goto invalid;
+        }
+
+    found:
+
+        if (i + sizeof(ngx_resolver_an_t) >= last) {
+            goto short_response;
+        }
+
+        an = (ngx_resolver_an_t *) &buf[i];
+
+        type = (an->type_hi << 8) + an->type_lo;
+        class = (an->class_hi << 8) + an->class_lo;
+        len = (an->len_hi << 8) + an->len_lo;
+        ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16)
+            + (an->ttl[2] << 8) + (an->ttl[3]);
+
+        if (class != 1) {
+            ngx_log_error(r->log_level, r->log, 0,
+                          "unexpected RR class %ui", class);
+            goto failed;
+        }
+
+        if (ttl < 0) {
+            ttl = 0;
+        }
+
+        ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
+                      "resolver qt:%ui cl:%ui len:%uz",
+                      type, class, len);
+
+        i += sizeof(ngx_resolver_an_t);
+
+        switch (type) {
+
+        case NGX_RESOLVE_PTR:
+
+            if (i + len > last) {
+                goto short_response;
+            }
+
+            goto ptr;
+
+            break;
+
+        case NGX_RESOLVE_CNAME:
+
+            break;
+
+        default:
+
+            ngx_log_error(r->log_level, r->log, 0,
+                          "unexpected RR type %ui", type);
+        }
+
+        i += len;
     }
 
-    /* compression pointer to *.arpa */
-
-    if (buf[i] != 0xc0 || buf[i + 1] != sizeof(ngx_resolver_hdr_t)) {
-        err = "invalid in-addr.arpa or ip6.arpa name in DNS response";
-        goto invalid;
-    }
-
-    an = (ngx_resolver_an_t *) &buf[i + 2];
-
-    class = (an->class_hi << 8) + an->class_lo;
-    len = (an->len_hi << 8) + an->len_lo;
-    ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16)
-        + (an->ttl[2] << 8) + (an->ttl[3]);
-
-    if (class != 1) {
-        ngx_log_error(r->log_level, r->log, 0,
-                      "unexpected RR class %ui", class);
-        goto failed;
-    }
-
-    if (ttl < 0) {
-        ttl = 0;
-    }
-
-    ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
-                  "resolver qt:%ui cl:%ui len:%uz",
-                  (an->type_hi << 8) + an->type_lo,
-                  class, len);
-
-    i += 2 + sizeof(ngx_resolver_an_t);
-
-    if (i + len > last) {
-        goto short_response;
-    }
+    /* unlock addr mutex */
+
+    ngx_log_error(r->log_level, r->log, 0,
+                  "no PTR type in DNS response");
+    return;
+
+ptr:
 
     if (ngx_resolver_copy(r, &name, buf, buf + i, buf + last) != NGX_OK) {
         goto failed;



More information about the nginx-devel mailing list