aboutsummaryrefslogtreecommitdiff
path: root/src/core/ngx_resolver.c
diff options
context:
space:
mode:
authorRuslan Ermilov <ru@nginx.com>2013-12-06 14:30:27 +0400
committerRuslan Ermilov <ru@nginx.com>2013-12-06 14:30:27 +0400
commitf57350cd86c46c789923482ae2adc4e59b58b6b5 (patch)
tree1a95be0b5952acb482d3238587371012556f98a2 /src/core/ngx_resolver.c
parentf3a271f3fd1ce763a7f8625562d480b7f5c02bd8 (diff)
downloadnginx-f57350cd86c46c789923482ae2adc4e59b58b6b5.tar.gz
nginx-f57350cd86c46c789923482ae2adc4e59b58b6b5.zip
Resolver: fixes in A processing.
Verify that class of RR is "IN". Verify that RR data length is exactly four octets. Correctly shift to the next RR if RR type is unknown.
Diffstat (limited to 'src/core/ngx_resolver.c')
-rw-r--r--src/core/ngx_resolver.c39
1 files changed, 25 insertions, 14 deletions
diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
index 1a81754ae..1fba5718f 100644
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -1179,7 +1179,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
uint32_t hash;
in_addr_t addr, *addrs;
ngx_str_t name;
- ngx_uint_t type, qident, naddrs, a, i, n, start;
+ ngx_uint_t type, class, qident, naddrs, a, i, n, start;
ngx_resolver_an_t *an;
ngx_resolver_ctx_t *ctx, *next;
ngx_resolver_node_t *rn;
@@ -1202,6 +1202,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
if (rn == NULL || rn->query == NULL) {
ngx_log_error(r->log_level, r->log, 0,
"unexpected response for %V", &name);
+ ngx_resolver_free(r, name.data);
goto failed;
}
@@ -1211,6 +1212,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
ngx_log_error(r->log_level, r->log, 0,
"wrong ident %ui response for %V, expect %ui",
ident, &name, qident);
+ ngx_resolver_free(r, name.data);
goto failed;
}
@@ -1287,21 +1289,33 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
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;
}
+ i += sizeof(ngx_resolver_an_t);
+
switch (type) {
case NGX_RESOLVE_A:
- i += sizeof(ngx_resolver_an_t);
+ if (len != 4) {
+ err = "invalid A record in DNS response";
+ goto invalid;
+ }
- if (i + len > last) {
+ if (i + 4 > last) {
goto short_response;
}
@@ -1310,21 +1324,16 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
naddrs++;
- i += len;
-
break;
case NGX_RESOLVE_CNAME:
- cname = &buf[i] + sizeof(ngx_resolver_an_t);
- i += sizeof(ngx_resolver_an_t) + len;
+ cname = &buf[i];
break;
case NGX_RESOLVE_DNAME:
- i += sizeof(ngx_resolver_an_t) + len;
-
break;
default:
@@ -1332,6 +1341,8 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
ngx_log_error(r->log_level, r->log, 0,
"unexpected RR type %ui", type);
}
+
+ i += len;
}
ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
@@ -1347,7 +1358,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
addrs = ngx_resolver_alloc(r, naddrs * sizeof(in_addr_t));
if (addrs == NULL) {
- return;
+ goto failed;
}
n = 0;
@@ -1395,7 +1406,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
addrs = ngx_resolver_dup(r, rn->u.addrs,
naddrs * sizeof(in_addr_t));
if (addrs == NULL) {
- return;
+ goto failed;
}
}
@@ -1439,7 +1450,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
/* CNAME only */
if (ngx_resolver_copy(r, &name, buf, cname, buf + last) != NGX_OK) {
- return;
+ goto failed;
}
ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
@@ -1467,6 +1478,8 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
ngx_resolver_free(r, rn->query);
rn->query = NULL;
+ /* unlock name mutex */
+
return;
}
@@ -1490,8 +1503,6 @@ failed:
/* unlock name mutex */
- ngx_resolver_free(r, name.data);
-
return;
}