Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nginx/nginx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuslan Ermilov <ru@nginx.com>2015-12-17 17:21:16 +0300
committerRuslan Ermilov <ru@nginx.com>2015-12-17 17:21:16 +0300
commitbf269cbc555798f0db04cad67cad130bca46010d (patch)
tree1e55cfaf5c6f757e2a82348632a30c3e8a33284d /src/core/ngx_resolver.c
parent06806aa0011b1562594574dff340f3b711885d7c (diff)
Resolver: improved PTR response processing.
The previous code only parsed the first answer, without checking its type, and required 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.
Diffstat (limited to 'src/core/ngx_resolver.c')
-rw-r--r--src/core/ngx_resolver.c102
1 files changed, 74 insertions, 28 deletions
diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
index 84e82443b..091ac8094 100644
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -2401,7 +2401,7 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
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;
@@ -2554,45 +2554,91 @@ valid:
i += sizeof(ngx_resolver_qs_t);
- if (i + 2 + sizeof(ngx_resolver_an_t) >= n) {
+ for (a = 0; a < nan; a++) {
+
+ start = i;
+
+ while (i < n) {
+
+ if (buf[i] & 0xc0) {
+ i += 2;
+ goto found;
+ }
+
+ if (buf[i] == 0) {
+ i++;
+ goto test_length;
+ }
+
+ i += 1 + buf[i];
+ }
+
goto short_response;
- }
- /* compression pointer to *.arpa */
+ test_length:
- 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;
- }
+ if (i - start < 2) {
+ err = "invalid name in DNS response";
+ goto invalid;
+ }
- an = (ngx_resolver_an_t *) &buf[i + 2];
+ found:
- 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 (i + sizeof(ngx_resolver_an_t) >= n) {
+ goto short_response;
+ }
- if (class != 1) {
- ngx_log_error(r->log_level, r->log, 0,
- "unexpected RR class %ui", class);
- goto failed;
- }
+ an = (ngx_resolver_an_t *) &buf[i];
- if (ttl < 0) {
- ttl = 0;
- }
+ 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]);
- 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);
+ if (class != 1) {
+ ngx_log_error(r->log_level, r->log, 0,
+ "unexpected RR class %ui", class);
+ goto failed;
+ }
- i += 2 + sizeof(ngx_resolver_an_t);
+ if (ttl < 0) {
+ ttl = 0;
+ }
- if (i + len > n) {
- goto short_response;
+ 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:
+
+ goto ptr;
+
+ case NGX_RESOLVE_CNAME:
+
+ break;
+
+ default:
+
+ ngx_log_error(r->log_level, r->log, 0,
+ "unexpected RR type %ui", type);
+ }
+
+ i += len;
}
+ /* 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 + n) != NGX_OK) {
goto failed;
}