Mercurial > hg > nginx
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 |