comparison src/core/ngx_resolver.c @ 5471:9c96782d9d05

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.
author Ruslan Ermilov <ru@nginx.com>
date Fri, 06 Dec 2013 14:30:27 +0400
parents aebdca7e8f8f
children ab493c60d9ff
comparison
equal deleted inserted replaced
5470:aebdca7e8f8f 5471:9c96782d9d05
1177 size_t len; 1177 size_t len;
1178 int32_t ttl; 1178 int32_t ttl;
1179 uint32_t hash; 1179 uint32_t hash;
1180 in_addr_t addr, *addrs; 1180 in_addr_t addr, *addrs;
1181 ngx_str_t name; 1181 ngx_str_t name;
1182 ngx_uint_t type, qident, naddrs, a, i, n, start; 1182 ngx_uint_t type, class, qident, naddrs, a, i, n, start;
1183 ngx_resolver_an_t *an; 1183 ngx_resolver_an_t *an;
1184 ngx_resolver_ctx_t *ctx, *next; 1184 ngx_resolver_ctx_t *ctx, *next;
1185 ngx_resolver_node_t *rn; 1185 ngx_resolver_node_t *rn;
1186 1186
1187 if (ngx_resolver_copy(r, &name, buf, 1187 if (ngx_resolver_copy(r, &name, buf,
1200 rn = ngx_resolver_lookup_name(r, &name, hash); 1200 rn = ngx_resolver_lookup_name(r, &name, hash);
1201 1201
1202 if (rn == NULL || rn->query == NULL) { 1202 if (rn == NULL || rn->query == NULL) {
1203 ngx_log_error(r->log_level, r->log, 0, 1203 ngx_log_error(r->log_level, r->log, 0,
1204 "unexpected response for %V", &name); 1204 "unexpected response for %V", &name);
1205 ngx_resolver_free(r, name.data);
1205 goto failed; 1206 goto failed;
1206 } 1207 }
1207 1208
1208 qident = (rn->query[0] << 8) + rn->query[1]; 1209 qident = (rn->query[0] << 8) + rn->query[1];
1209 1210
1210 if (ident != qident) { 1211 if (ident != qident) {
1211 ngx_log_error(r->log_level, r->log, 0, 1212 ngx_log_error(r->log_level, r->log, 0,
1212 "wrong ident %ui response for %V, expect %ui", 1213 "wrong ident %ui response for %V, expect %ui",
1213 ident, &name, qident); 1214 ident, &name, qident);
1215 ngx_resolver_free(r, name.data);
1214 goto failed; 1216 goto failed;
1215 } 1217 }
1216 1218
1217 ngx_resolver_free(r, name.data); 1219 ngx_resolver_free(r, name.data);
1218 1220
1285 } 1287 }
1286 1288
1287 an = (ngx_resolver_an_t *) &buf[i]; 1289 an = (ngx_resolver_an_t *) &buf[i];
1288 1290
1289 type = (an->type_hi << 8) + an->type_lo; 1291 type = (an->type_hi << 8) + an->type_lo;
1292 class = (an->class_hi << 8) + an->class_lo;
1290 len = (an->len_hi << 8) + an->len_lo; 1293 len = (an->len_hi << 8) + an->len_lo;
1291 ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16) 1294 ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16)
1292 + (an->ttl[2] << 8) + (an->ttl[3]); 1295 + (an->ttl[2] << 8) + (an->ttl[3]);
1293 1296
1297 if (class != 1) {
1298 ngx_log_error(r->log_level, r->log, 0,
1299 "unexpected RR class %ui", class);
1300 goto failed;
1301 }
1302
1294 if (ttl < 0) { 1303 if (ttl < 0) {
1295 ttl = 0; 1304 ttl = 0;
1296 } 1305 }
1297 1306
1307 i += sizeof(ngx_resolver_an_t);
1308
1298 switch (type) { 1309 switch (type) {
1299 1310
1300 case NGX_RESOLVE_A: 1311 case NGX_RESOLVE_A:
1301 1312
1302 i += sizeof(ngx_resolver_an_t); 1313 if (len != 4) {
1303 1314 err = "invalid A record in DNS response";
1304 if (i + len > last) { 1315 goto invalid;
1316 }
1317
1318 if (i + 4 > last) {
1305 goto short_response; 1319 goto short_response;
1306 } 1320 }
1307 1321
1308 addr = htonl((buf[i] << 24) + (buf[i + 1] << 16) 1322 addr = htonl((buf[i] << 24) + (buf[i + 1] << 16)
1309 + (buf[i + 2] << 8) + (buf[i + 3])); 1323 + (buf[i + 2] << 8) + (buf[i + 3]));
1310 1324
1311 naddrs++; 1325 naddrs++;
1312 1326
1313 i += len;
1314
1315 break; 1327 break;
1316 1328
1317 case NGX_RESOLVE_CNAME: 1329 case NGX_RESOLVE_CNAME:
1318 1330
1319 cname = &buf[i] + sizeof(ngx_resolver_an_t); 1331 cname = &buf[i];
1320 i += sizeof(ngx_resolver_an_t) + len;
1321 1332
1322 break; 1333 break;
1323 1334
1324 case NGX_RESOLVE_DNAME: 1335 case NGX_RESOLVE_DNAME:
1325
1326 i += sizeof(ngx_resolver_an_t) + len;
1327 1336
1328 break; 1337 break;
1329 1338
1330 default: 1339 default:
1331 1340
1332 ngx_log_error(r->log_level, r->log, 0, 1341 ngx_log_error(r->log_level, r->log, 0,
1333 "unexpected RR type %ui", type); 1342 "unexpected RR type %ui", type);
1334 } 1343 }
1344
1345 i += len;
1335 } 1346 }
1336 1347
1337 ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0, 1348 ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
1338 "resolver naddrs:%ui cname:%p ttl:%d", 1349 "resolver naddrs:%ui cname:%p ttl:%d",
1339 naddrs, cname, ttl); 1350 naddrs, cname, ttl);
1345 1356
1346 } else { 1357 } else {
1347 1358
1348 addrs = ngx_resolver_alloc(r, naddrs * sizeof(in_addr_t)); 1359 addrs = ngx_resolver_alloc(r, naddrs * sizeof(in_addr_t));
1349 if (addrs == NULL) { 1360 if (addrs == NULL) {
1350 return; 1361 goto failed;
1351 } 1362 }
1352 1363
1353 n = 0; 1364 n = 0;
1354 i = ans; 1365 i = ans;
1355 1366
1393 rn->u.addrs = addrs; 1404 rn->u.addrs = addrs;
1394 1405
1395 addrs = ngx_resolver_dup(r, rn->u.addrs, 1406 addrs = ngx_resolver_dup(r, rn->u.addrs,
1396 naddrs * sizeof(in_addr_t)); 1407 naddrs * sizeof(in_addr_t));
1397 if (addrs == NULL) { 1408 if (addrs == NULL) {
1398 return; 1409 goto failed;
1399 } 1410 }
1400 } 1411 }
1401 1412
1402 rn->naddrs = (u_short) naddrs; 1413 rn->naddrs = (u_short) naddrs;
1403 1414
1437 if (cname) { 1448 if (cname) {
1438 1449
1439 /* CNAME only */ 1450 /* CNAME only */
1440 1451
1441 if (ngx_resolver_copy(r, &name, buf, cname, buf + last) != NGX_OK) { 1452 if (ngx_resolver_copy(r, &name, buf, cname, buf + last) != NGX_OK) {
1442 return; 1453 goto failed;
1443 } 1454 }
1444 1455
1445 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, 1456 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
1446 "resolver cname:\"%V\"", &name); 1457 "resolver cname:\"%V\"", &name);
1447 1458
1464 (void) ngx_resolve_name_locked(r, ctx); 1475 (void) ngx_resolve_name_locked(r, ctx);
1465 } 1476 }
1466 1477
1467 ngx_resolver_free(r, rn->query); 1478 ngx_resolver_free(r, rn->query);
1468 rn->query = NULL; 1479 rn->query = NULL;
1480
1481 /* unlock name mutex */
1469 1482
1470 return; 1483 return;
1471 } 1484 }
1472 1485
1473 ngx_log_error(r->log_level, r->log, 0, 1486 ngx_log_error(r->log_level, r->log, 0,
1487 return; 1500 return;
1488 1501
1489 failed: 1502 failed:
1490 1503
1491 /* unlock name mutex */ 1504 /* unlock name mutex */
1492
1493 ngx_resolver_free(r, name.data);
1494 1505
1495 return; 1506 return;
1496 } 1507 }
1497 1508
1498 1509