comparison src/core/ngx_resolver.c @ 5477:98876ce2a7fd

Resolver: implemented IPv6 name to address resolving.
author Ruslan Ermilov <ru@nginx.com>
date Mon, 09 Dec 2013 10:53:28 +0400
parents 950c9ed3e66f
children 3cb3175a6fef
comparison
equal deleted inserted replaced
5476:950c9ed3e66f 5477:98876ce2a7fd
68 ngx_queue_t *queue); 68 ngx_queue_t *queue);
69 static void ngx_resolver_read_response(ngx_event_t *rev); 69 static void ngx_resolver_read_response(ngx_event_t *rev);
70 static void ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, 70 static void ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf,
71 size_t n); 71 size_t n);
72 static void ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n, 72 static void ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
73 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan, ngx_uint_t ans); 73 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t qtype,
74 ngx_uint_t nan, ngx_uint_t ans);
74 static void ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n, 75 static void ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
75 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan); 76 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan);
76 static ngx_resolver_node_t *ngx_resolver_lookup_name(ngx_resolver_t *r, 77 static ngx_resolver_node_t *ngx_resolver_lookup_name(ngx_resolver_t *r,
77 ngx_str_t *name, uint32_t hash); 78 ngx_str_t *name, uint32_t hash);
78 static ngx_resolver_node_t *ngx_resolver_lookup_addr(ngx_resolver_t *r, 79 static ngx_resolver_node_t *ngx_resolver_lookup_addr(ngx_resolver_t *r,
86 static void *ngx_resolver_alloc(ngx_resolver_t *r, size_t size); 87 static void *ngx_resolver_alloc(ngx_resolver_t *r, size_t size);
87 static void *ngx_resolver_calloc(ngx_resolver_t *r, size_t size); 88 static void *ngx_resolver_calloc(ngx_resolver_t *r, size_t size);
88 static void ngx_resolver_free(ngx_resolver_t *r, void *p); 89 static void ngx_resolver_free(ngx_resolver_t *r, void *p);
89 static void ngx_resolver_free_locked(ngx_resolver_t *r, void *p); 90 static void ngx_resolver_free_locked(ngx_resolver_t *r, void *p);
90 static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size); 91 static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size);
91 static ngx_addr_t *ngx_resolver_export(ngx_resolver_t *r, in_addr_t *src, 92 static ngx_addr_t *ngx_resolver_export(ngx_resolver_t *r,
92 ngx_uint_t n, ngx_uint_t rotate); 93 ngx_resolver_node_t *rn, ngx_uint_t rotate);
93 static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len); 94 static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len);
94 95
95 #if (NGX_HAVE_INET6) 96 #if (NGX_HAVE_INET6)
96 static void ngx_resolver_rbtree_insert_addr6_value(ngx_rbtree_node_t *temp, 97 static void ngx_resolver_rbtree_insert_addr6_value(ngx_rbtree_node_t *temp,
97 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); 98 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
433 434
434 /* unlock alloc mutex */ 435 /* unlock alloc mutex */
435 } 436 }
436 437
437 438
438 /* NGX_RESOLVE_A only */
439
440 static ngx_int_t 439 static ngx_int_t
441 ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx) 440 ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
442 { 441 {
443 uint32_t hash; 442 uint32_t hash;
444 ngx_int_t rc; 443 ngx_int_t rc;
461 460
462 rn->expire = ngx_time() + r->expire; 461 rn->expire = ngx_time() + r->expire;
463 462
464 ngx_queue_insert_head(&r->name_expire_queue, &rn->queue); 463 ngx_queue_insert_head(&r->name_expire_queue, &rn->queue);
465 464
466 naddrs = rn->naddrs; 465 naddrs = (rn->naddrs == (u_short) -1) ? 0 : rn->naddrs;
466 #if (NGX_HAVE_INET6)
467 naddrs += (rn->naddrs6 == (u_short) -1) ? 0 : rn->naddrs6;
468 #endif
467 469
468 if (naddrs) { 470 if (naddrs) {
469 471
470 /* NGX_RESOLVE_A answer */ 472 if (naddrs == 1 && rn->naddrs == 1) {
471
472 if (naddrs == 1) {
473 addrs = NULL; 473 addrs = NULL;
474 474
475 } else { 475 } else {
476 addrs = ngx_resolver_export(r, rn->u.addrs, naddrs, 1); 476 addrs = ngx_resolver_export(r, rn, 1);
477 if (addrs == NULL) { 477 if (addrs == NULL) {
478 return NGX_ERROR; 478 return NGX_ERROR;
479 } 479 }
480 } 480 }
481 481
556 /* lock alloc mutex */ 556 /* lock alloc mutex */
557 557
558 if (rn->query) { 558 if (rn->query) {
559 ngx_resolver_free_locked(r, rn->query); 559 ngx_resolver_free_locked(r, rn->query);
560 rn->query = NULL; 560 rn->query = NULL;
561 #if (NGX_HAVE_INET6)
562 rn->query6 = NULL;
563 #endif
561 } 564 }
562 565
563 if (rn->cnlen) { 566 if (rn->cnlen) {
564 ngx_resolver_free_locked(r, rn->u.cname); 567 ngx_resolver_free_locked(r, rn->u.cname);
565 } 568 }
566 569
567 if (rn->naddrs > 1) { 570 if (rn->naddrs > 1 && rn->naddrs != (u_short) -1) {
568 ngx_resolver_free_locked(r, rn->u.addrs); 571 ngx_resolver_free_locked(r, rn->u.addrs);
569 } 572 }
573
574 #if (NGX_HAVE_INET6)
575 if (rn->naddrs6 > 1 && rn->naddrs6 != (u_short) -1) {
576 ngx_resolver_free_locked(r, rn->u6.addrs6);
577 }
578 #endif
570 579
571 /* unlock alloc mutex */ 580 /* unlock alloc mutex */
572 581
573 } else { 582 } else {
574 583
584 } 593 }
585 594
586 rn->node.key = hash; 595 rn->node.key = hash;
587 rn->nlen = (u_short) ctx->name.len; 596 rn->nlen = (u_short) ctx->name.len;
588 rn->query = NULL; 597 rn->query = NULL;
598 #if (NGX_HAVE_INET6)
599 rn->query6 = NULL;
600 #endif
589 601
590 ngx_rbtree_insert(&r->name_rbtree, &rn->node); 602 ngx_rbtree_insert(&r->name_rbtree, &rn->node);
591 } 603 }
592 604
593 rc = ngx_resolver_create_name_query(rn, ctx); 605 rc = ngx_resolver_create_name_query(rn, ctx);
606 ctx->state = NGX_RESOLVE_NXDOMAIN; 618 ctx->state = NGX_RESOLVE_NXDOMAIN;
607 ctx->handler(ctx); 619 ctx->handler(ctx);
608 620
609 return NGX_OK; 621 return NGX_OK;
610 } 622 }
623
624 rn->naddrs = (u_short) -1;
625 #if (NGX_HAVE_INET6)
626 rn->naddrs6 = (u_short) -1;
627 #endif
611 628
612 if (ngx_resolver_send_query(r, rn) != NGX_OK) { 629 if (ngx_resolver_send_query(r, rn) != NGX_OK) {
613 goto failed; 630 goto failed;
614 } 631 }
615 632
633 650
634 rn->expire = ngx_time() + r->resend_timeout; 651 rn->expire = ngx_time() + r->resend_timeout;
635 652
636 ngx_queue_insert_head(&r->name_resend_queue, &rn->queue); 653 ngx_queue_insert_head(&r->name_resend_queue, &rn->queue);
637 654
655 rn->code = 0;
638 rn->cnlen = 0; 656 rn->cnlen = 0;
639 rn->naddrs = 0;
640 rn->valid = 0; 657 rn->valid = 0;
641 rn->waiting = ctx; 658 rn->waiting = ctx;
642 659
643 ctx->state = NGX_AGAIN; 660 ctx->state = NGX_AGAIN;
644 661
760 777
761 ngx_queue_remove(&rn->queue); 778 ngx_queue_remove(&rn->queue);
762 779
763 ngx_resolver_free(r, rn->query); 780 ngx_resolver_free(r, rn->query);
764 rn->query = NULL; 781 rn->query = NULL;
782 #if (NGX_HAVE_INET6)
783 rn->query6 = NULL;
784 #endif
765 785
766 } else { 786 } else {
767 rn = ngx_resolver_alloc(r, sizeof(ngx_resolver_node_t)); 787 rn = ngx_resolver_alloc(r, sizeof(ngx_resolver_node_t));
768 if (rn == NULL) { 788 if (rn == NULL) {
769 goto failed; 789 goto failed;
781 default: /* AF_INET */ 801 default: /* AF_INET */
782 rn->node.key = addr; 802 rn->node.key = addr;
783 } 803 }
784 804
785 rn->query = NULL; 805 rn->query = NULL;
806 #if (NGX_HAVE_INET6)
807 rn->query6 = NULL;
808 #endif
786 809
787 ngx_rbtree_insert(tree, &rn->node); 810 ngx_rbtree_insert(tree, &rn->node);
788 } 811 }
789 812
790 if (ngx_resolver_create_addr_query(rn, ctx) != NGX_OK) { 813 if (ngx_resolver_create_addr_query(rn, ctx) != NGX_OK) {
791 goto failed; 814 goto failed;
792 } 815 }
816
817 rn->naddrs = (u_short) -1;
818 #if (NGX_HAVE_INET6)
819 rn->naddrs6 = (u_short) -1;
820 #endif
793 821
794 if (ngx_resolver_send_query(r, rn) != NGX_OK) { 822 if (ngx_resolver_send_query(r, rn) != NGX_OK) {
795 goto failed; 823 goto failed;
796 } 824 }
797 825
813 841
814 rn->expire = ngx_time() + r->resend_timeout; 842 rn->expire = ngx_time() + r->resend_timeout;
815 843
816 ngx_queue_insert_head(resend_queue, &rn->queue); 844 ngx_queue_insert_head(resend_queue, &rn->queue);
817 845
846 rn->code = 0;
818 rn->cnlen = 0; 847 rn->cnlen = 0;
819 rn->naddrs = 0;
820 rn->name = NULL; 848 rn->name = NULL;
821 rn->nlen = 0; 849 rn->nlen = 0;
822 rn->valid = 0; 850 rn->valid = 0;
823 rn->waiting = ctx; 851 rn->waiting = ctx;
824 852
1021 uc->connection->data = r; 1049 uc->connection->data = r;
1022 uc->connection->read->handler = ngx_resolver_read_response; 1050 uc->connection->read->handler = ngx_resolver_read_response;
1023 uc->connection->read->resolver = 1; 1051 uc->connection->read->resolver = 1;
1024 } 1052 }
1025 1053
1026 n = ngx_send(uc->connection, rn->query, rn->qlen); 1054 if (rn->naddrs == (u_short) -1) {
1027 1055 n = ngx_send(uc->connection, rn->query, rn->qlen);
1028 if (n == -1) { 1056
1029 return NGX_ERROR; 1057 if (n == -1) {
1030 } 1058 return NGX_ERROR;
1031 1059 }
1032 if ((size_t) n != (size_t) rn->qlen) { 1060
1033 ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete"); 1061 if ((size_t) n != (size_t) rn->qlen) {
1034 return NGX_ERROR; 1062 ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete");
1035 } 1063 return NGX_ERROR;
1064 }
1065 }
1066
1067 #if (NGX_HAVE_INET6)
1068 if (rn->query6 && rn->naddrs6 == (u_short) -1) {
1069 n = ngx_send(uc->connection, rn->query6, rn->qlen);
1070
1071 if (n == -1) {
1072 return NGX_ERROR;
1073 }
1074
1075 if ((size_t) n != (size_t) rn->qlen) {
1076 ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete");
1077 return NGX_ERROR;
1078 }
1079 }
1080 #endif
1036 1081
1037 return NGX_OK; 1082 return NGX_OK;
1038 } 1083 }
1039 1084
1040 1085
1172 ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n) 1217 ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n)
1173 { 1218 {
1174 char *err; 1219 char *err;
1175 ngx_uint_t i, times, ident, qident, flags, code, nqs, nan, 1220 ngx_uint_t i, times, ident, qident, flags, code, nqs, nan,
1176 qtype, qclass; 1221 qtype, qclass;
1222 #if (NGX_HAVE_INET6)
1223 ngx_uint_t qident6;
1224 #endif
1177 ngx_queue_t *q; 1225 ngx_queue_t *q;
1178 ngx_resolver_qs_t *qs; 1226 ngx_resolver_qs_t *qs;
1179 ngx_resolver_hdr_t *response; 1227 ngx_resolver_hdr_t *response;
1180 ngx_resolver_node_t *rn; 1228 ngx_resolver_node_t *rn;
1181 1229
1215 { 1263 {
1216 rn = ngx_queue_data(q, ngx_resolver_node_t, queue); 1264 rn = ngx_queue_data(q, ngx_resolver_node_t, queue);
1217 qident = (rn->query[0] << 8) + rn->query[1]; 1265 qident = (rn->query[0] << 8) + rn->query[1];
1218 1266
1219 if (qident == ident) { 1267 if (qident == ident) {
1220 ngx_log_error(r->log_level, r->log, 0, 1268 goto dns_error_name;
1221 "DNS error (%ui: %s), query id:%ui, name:\"%*s\"", 1269 }
1222 code, ngx_resolver_strerror(code), ident, 1270
1223 rn->nlen, rn->name); 1271 #if (NGX_HAVE_INET6)
1224 return; 1272 if (rn->query6) {
1225 } 1273 qident6 = (rn->query6[0] << 8) + rn->query6[1];
1274
1275 if (qident6 == ident) {
1276 goto dns_error_name;
1277 }
1278 }
1279 #endif
1226 } 1280 }
1227 1281
1228 goto dns_error; 1282 goto dns_error;
1229 } 1283 }
1230 1284
1277 } 1331 }
1278 1332
1279 switch (qtype) { 1333 switch (qtype) {
1280 1334
1281 case NGX_RESOLVE_A: 1335 case NGX_RESOLVE_A:
1282 1336 #if (NGX_HAVE_INET6)
1283 ngx_resolver_process_a(r, buf, n, ident, code, nan, 1337 case NGX_RESOLVE_AAAA:
1338 #endif
1339
1340 ngx_resolver_process_a(r, buf, n, ident, code, qtype, nan,
1284 i + sizeof(ngx_resolver_qs_t)); 1341 i + sizeof(ngx_resolver_qs_t));
1285 1342
1286 break; 1343 break;
1287 1344
1288 case NGX_RESOLVE_PTR: 1345 case NGX_RESOLVE_PTR:
1307 1364
1308 ngx_log_error(r->log_level, r->log, 0, err); 1365 ngx_log_error(r->log_level, r->log, 0, err);
1309 1366
1310 return; 1367 return;
1311 1368
1369 dns_error_name:
1370
1371 ngx_log_error(r->log_level, r->log, 0,
1372 "DNS error (%ui: %s), query id:%ui, name:\"%*s\"",
1373 code, ngx_resolver_strerror(code), ident,
1374 rn->nlen, rn->name);
1375 return;
1376
1312 dns_error: 1377 dns_error:
1313 1378
1314 ngx_log_error(r->log_level, r->log, 0, 1379 ngx_log_error(r->log_level, r->log, 0,
1315 "DNS error (%ui: %s), query id:%ui", 1380 "DNS error (%ui: %s), query id:%ui",
1316 code, ngx_resolver_strerror(code), ident); 1381 code, ngx_resolver_strerror(code), ident);
1318 } 1383 }
1319 1384
1320 1385
1321 static void 1386 static void
1322 ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last, 1387 ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
1323 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan, ngx_uint_t ans) 1388 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t qtype,
1389 ngx_uint_t nan, ngx_uint_t ans)
1324 { 1390 {
1325 char *err; 1391 char *err;
1326 u_char *cname; 1392 u_char *cname;
1327 size_t len; 1393 size_t len;
1328 int32_t ttl; 1394 int32_t ttl;
1329 uint32_t hash; 1395 uint32_t hash;
1330 in_addr_t *addr; 1396 in_addr_t *addr;
1331 ngx_str_t name; 1397 ngx_str_t name;
1332 ngx_addr_t *addrs; 1398 ngx_addr_t *addrs;
1333 ngx_uint_t type, class, qident, naddrs, a, i, n, start; 1399 ngx_uint_t type, class, qident, naddrs, a, i, n, start;
1400 #if (NGX_HAVE_INET6)
1401 struct in6_addr *addr6;
1402 #endif
1334 ngx_resolver_an_t *an; 1403 ngx_resolver_an_t *an;
1335 ngx_resolver_ctx_t *ctx, *next; 1404 ngx_resolver_ctx_t *ctx, *next;
1336 ngx_resolver_node_t *rn; 1405 ngx_resolver_node_t *rn;
1337 1406
1338 if (ngx_resolver_copy(r, &name, buf, 1407 if (ngx_resolver_copy(r, &name, buf,
1348 1417
1349 /* lock name mutex */ 1418 /* lock name mutex */
1350 1419
1351 rn = ngx_resolver_lookup_name(r, &name, hash); 1420 rn = ngx_resolver_lookup_name(r, &name, hash);
1352 1421
1353 if (rn == NULL || rn->query == NULL) { 1422 if (rn == NULL) {
1354 ngx_log_error(r->log_level, r->log, 0, 1423 ngx_log_error(r->log_level, r->log, 0,
1355 "unexpected response for %V", &name); 1424 "unexpected response for %V", &name);
1356 ngx_resolver_free(r, name.data); 1425 ngx_resolver_free(r, name.data);
1357 goto failed; 1426 goto failed;
1358 } 1427 }
1359 1428
1360 qident = (rn->query[0] << 8) + rn->query[1]; 1429 switch (qtype) {
1430
1431 #if (NGX_HAVE_INET6)
1432 case NGX_RESOLVE_AAAA:
1433
1434 if (rn->query6 == NULL || rn->naddrs6 != (u_short) -1) {
1435 ngx_log_error(r->log_level, r->log, 0,
1436 "unexpected response for %V", &name);
1437 ngx_resolver_free(r, name.data);
1438 goto failed;
1439 }
1440
1441 rn->naddrs6 = 0;
1442 qident = (rn->query6[0] << 8) + rn->query6[1];
1443
1444 break;
1445 #endif
1446
1447 default: /* NGX_RESOLVE_A */
1448
1449 if (rn->query == NULL || rn->naddrs != (u_short) -1) {
1450 ngx_log_error(r->log_level, r->log, 0,
1451 "unexpected response for %V", &name);
1452 ngx_resolver_free(r, name.data);
1453 goto failed;
1454 }
1455
1456 rn->naddrs = 0;
1457 qident = (rn->query[0] << 8) + rn->query[1];
1458 }
1361 1459
1362 if (ident != qident) { 1460 if (ident != qident) {
1363 ngx_log_error(r->log_level, r->log, 0, 1461 ngx_log_error(r->log_level, r->log, 0,
1364 "wrong ident %ui response for %V, expect %ui", 1462 "wrong ident %ui response for %V, expect %ui",
1365 ident, &name, qident); 1463 ident, &name, qident);
1367 goto failed; 1465 goto failed;
1368 } 1466 }
1369 1467
1370 ngx_resolver_free(r, name.data); 1468 ngx_resolver_free(r, name.data);
1371 1469
1470 if (code == 0 && rn->code) {
1471 code = rn->code;
1472 }
1473
1372 if (code == 0 && nan == 0) { 1474 if (code == 0 && nan == 0) {
1475
1476 #if (NGX_HAVE_INET6)
1477 switch (qtype) {
1478
1479 case NGX_RESOLVE_AAAA:
1480
1481 if (rn->naddrs == (u_short) -1) {
1482 goto next;
1483 }
1484
1485 if (rn->naddrs) {
1486 goto export;
1487 }
1488
1489 break;
1490
1491 default: /* NGX_RESOLVE_A */
1492
1493 if (rn->naddrs6 == (u_short) -1) {
1494 goto next;
1495 }
1496
1497 if (rn->naddrs6) {
1498 goto export;
1499 }
1500 }
1501 #endif
1502
1373 code = NGX_RESOLVE_NXDOMAIN; 1503 code = NGX_RESOLVE_NXDOMAIN;
1374 } 1504 }
1375 1505
1376 if (code) { 1506 if (code) {
1507
1508 #if (NGX_HAVE_INET6)
1509 switch (qtype) {
1510
1511 case NGX_RESOLVE_AAAA:
1512
1513 if (rn->naddrs == (u_short) -1) {
1514 rn->code = (u_char) code;
1515 goto next;
1516 }
1517
1518 break;
1519
1520 default: /* NGX_RESOLVE_A */
1521
1522 if (rn->naddrs6 == (u_short) -1) {
1523 rn->code = (u_char) code;
1524 goto next;
1525 }
1526 }
1527 #endif
1528
1377 next = rn->waiting; 1529 next = rn->waiting;
1378 rn->waiting = NULL; 1530 rn->waiting = NULL;
1379 1531
1380 ngx_queue_remove(&rn->queue); 1532 ngx_queue_remove(&rn->queue);
1381 1533
1457 1609
1458 switch (type) { 1610 switch (type) {
1459 1611
1460 case NGX_RESOLVE_A: 1612 case NGX_RESOLVE_A:
1461 1613
1614 if (qtype != NGX_RESOLVE_A) {
1615 err = "unexpected A record in DNS response";
1616 goto invalid;
1617 }
1618
1462 if (len != 4) { 1619 if (len != 4) {
1463 err = "invalid A record in DNS response"; 1620 err = "invalid A record in DNS response";
1464 goto invalid; 1621 goto invalid;
1465 } 1622 }
1466 1623
1470 1627
1471 naddrs++; 1628 naddrs++;
1472 1629
1473 break; 1630 break;
1474 1631
1632 #if (NGX_HAVE_INET6)
1633 case NGX_RESOLVE_AAAA:
1634
1635 if (qtype != NGX_RESOLVE_AAAA) {
1636 err = "unexpected AAAA record in DNS response";
1637 goto invalid;
1638 }
1639
1640 if (len != 16) {
1641 err = "invalid AAAA record in DNS response";
1642 goto invalid;
1643 }
1644
1645 if (i + 16 > last) {
1646 goto short_response;
1647 }
1648
1649 naddrs++;
1650
1651 break;
1652 #endif
1653
1475 case NGX_RESOLVE_CNAME: 1654 case NGX_RESOLVE_CNAME:
1476 1655
1477 cname = &buf[i]; 1656 cname = &buf[i];
1478 1657
1479 break; 1658 break;
1495 "resolver naddrs:%ui cname:%p ttl:%d", 1674 "resolver naddrs:%ui cname:%p ttl:%d",
1496 naddrs, cname, ttl); 1675 naddrs, cname, ttl);
1497 1676
1498 if (naddrs) { 1677 if (naddrs) {
1499 1678
1500 if (naddrs == 1) { 1679 switch (qtype) {
1501 addr = &rn->u.addr; 1680
1502 rn->naddrs = 1; 1681 #if (NGX_HAVE_INET6)
1503 1682 case NGX_RESOLVE_AAAA:
1504 } else { 1683
1505 addr = ngx_resolver_alloc(r, naddrs * sizeof(in_addr_t)); 1684 if (naddrs == 1) {
1506 if (addr == NULL) { 1685 addr6 = &rn->u6.addr6;
1507 goto failed; 1686 rn->naddrs6 = 1;
1508 } 1687
1509 1688 } else {
1510 rn->u.addrs = addr; 1689 addr6 = ngx_resolver_alloc(r, naddrs * sizeof(struct in6_addr));
1511 rn->naddrs = (u_short) naddrs; 1690 if (addr6 == NULL) {
1512 } 1691 goto failed;
1692 }
1693
1694 rn->u6.addrs6 = addr6;
1695 rn->naddrs6 = (u_short) naddrs;
1696 }
1697
1698 #if (NGX_SUPPRESS_WARN)
1699 addr = NULL;
1700 #endif
1701
1702 break;
1703 #endif
1704
1705 default: /* NGX_RESOLVE_A */
1706
1707 if (naddrs == 1) {
1708 addr = &rn->u.addr;
1709 rn->naddrs = 1;
1710
1711 } else {
1712 addr = ngx_resolver_alloc(r, naddrs * sizeof(in_addr_t));
1713 if (addr == NULL) {
1714 goto failed;
1715 }
1716
1717 rn->u.addrs = addr;
1718 rn->naddrs = (u_short) naddrs;
1719 }
1720
1721 #if (NGX_HAVE_INET6 && NGX_SUPPRESS_WARN)
1722 addr6 = NULL;
1723 #endif
1724 }
1725
1726 rn->ttl = ttl;
1513 1727
1514 n = 0; 1728 n = 0;
1515 i = ans; 1729 i = ans;
1516 1730
1517 for (a = 0; a < nan; a++) { 1731 for (a = 0; a < nan; a++) {
1542 1756
1543 addr[n] = htonl((buf[i] << 24) + (buf[i + 1] << 16) 1757 addr[n] = htonl((buf[i] << 24) + (buf[i + 1] << 16)
1544 + (buf[i + 2] << 8) + (buf[i + 3])); 1758 + (buf[i + 2] << 8) + (buf[i + 3]));
1545 1759
1546 if (++n == naddrs) { 1760 if (++n == naddrs) {
1761
1762 #if (NGX_HAVE_INET6)
1763 if (rn->naddrs6 == (u_short) -1) {
1764 goto next;
1765 }
1766 #endif
1767
1547 break; 1768 break;
1548 } 1769 }
1549 } 1770 }
1550 1771
1772 #if (NGX_HAVE_INET6)
1773 else if (type == NGX_RESOLVE_AAAA) {
1774
1775 ngx_memcpy(addr6[n].s6_addr, &buf[i], 16);
1776
1777 if (++n == naddrs) {
1778
1779 if (rn->naddrs == (u_short) -1) {
1780 goto next;
1781 }
1782
1783 break;
1784 }
1785 }
1786 #endif
1787
1551 i += len; 1788 i += len;
1552 } 1789 }
1553 1790 }
1554 if (naddrs == 1) { 1791
1792 if (rn->naddrs != (u_short) -1
1793 #if (NGX_HAVE_INET6)
1794 && rn->naddrs6 != (u_short) -1
1795 #endif
1796 && rn->naddrs
1797 #if (NGX_HAVE_INET6)
1798 + rn->naddrs6
1799 #endif
1800 > 0)
1801 {
1802
1803 #if (NGX_HAVE_INET6)
1804 export:
1805 #endif
1806
1807 naddrs = rn->naddrs;
1808 #if (NGX_HAVE_INET6)
1809 naddrs += rn->naddrs6;
1810 #endif
1811
1812 if (naddrs == 1 && rn->naddrs == 1) {
1555 addrs = NULL; 1813 addrs = NULL;
1556 1814
1557 } else { 1815 } else {
1558 addrs = ngx_resolver_export(r, rn->u.addrs, naddrs, 0); 1816 addrs = ngx_resolver_export(r, rn, 0);
1559 if (addrs == NULL) { 1817 if (addrs == NULL) {
1560 goto failed; 1818 goto failed;
1561 } 1819 }
1562 } 1820 }
1563 1821
1564 ngx_queue_remove(&rn->queue); 1822 ngx_queue_remove(&rn->queue);
1565 1823
1566 rn->valid = ngx_time() + (r->valid ? r->valid : ttl); 1824 rn->valid = ngx_time() + (r->valid ? r->valid : (time_t) rn->ttl);
1567 rn->expire = ngx_time() + r->expire; 1825 rn->expire = ngx_time() + r->expire;
1568 1826
1569 ngx_queue_insert_head(&r->name_expire_queue, &rn->queue); 1827 ngx_queue_insert_head(&r->name_expire_queue, &rn->queue);
1570 1828
1571 next = rn->waiting; 1829 next = rn->waiting;
1600 ngx_resolver_free(r, addrs); 1858 ngx_resolver_free(r, addrs);
1601 } 1859 }
1602 1860
1603 ngx_resolver_free(r, rn->query); 1861 ngx_resolver_free(r, rn->query);
1604 rn->query = NULL; 1862 rn->query = NULL;
1863 #if (NGX_HAVE_INET6)
1864 rn->query6 = NULL;
1865 #endif
1605 1866
1606 return; 1867 return;
1607 } 1868 }
1608 1869
1609 if (cname) { 1870 if (cname) {
1610 1871
1611 /* CNAME only */ 1872 /* CNAME only */
1873
1874 if (rn->naddrs == (u_short) -1
1875 #if (NGX_HAVE_INET6)
1876 || rn->naddrs6 == (u_short) -1
1877 #endif
1878 )
1879 {
1880 goto next;
1881 }
1612 1882
1613 if (ngx_resolver_copy(r, &name, buf, cname, buf + last) != NGX_OK) { 1883 if (ngx_resolver_copy(r, &name, buf, cname, buf + last) != NGX_OK) {
1614 goto failed; 1884 goto failed;
1615 } 1885 }
1616 1886
1636 (void) ngx_resolve_name_locked(r, ctx); 1906 (void) ngx_resolve_name_locked(r, ctx);
1637 } 1907 }
1638 1908
1639 ngx_resolver_free(r, rn->query); 1909 ngx_resolver_free(r, rn->query);
1640 rn->query = NULL; 1910 rn->query = NULL;
1911 #if (NGX_HAVE_INET6)
1912 rn->query6 = NULL;
1913 #endif
1641 1914
1642 /* unlock name mutex */ 1915 /* unlock name mutex */
1643 1916
1644 return; 1917 return;
1645 } 1918 }
1659 ngx_log_error(r->log_level, r->log, 0, err); 1932 ngx_log_error(r->log_level, r->log, 0, err);
1660 1933
1661 return; 1934 return;
1662 1935
1663 failed: 1936 failed:
1937
1938 next:
1664 1939
1665 /* unlock name mutex */ 1940 /* unlock name mutex */
1666 1941
1667 return; 1942 return;
1668 } 1943 }
2153 2428
2154 nlen = ctx->name.len ? (1 + ctx->name.len + 1) : 1; 2429 nlen = ctx->name.len ? (1 + ctx->name.len + 1) : 1;
2155 2430
2156 len = sizeof(ngx_resolver_hdr_t) + nlen + sizeof(ngx_resolver_qs_t); 2431 len = sizeof(ngx_resolver_hdr_t) + nlen + sizeof(ngx_resolver_qs_t);
2157 2432
2433 #if (NGX_HAVE_INET6)
2434 p = ngx_resolver_alloc(ctx->resolver, len * 2);
2435 #else
2158 p = ngx_resolver_alloc(ctx->resolver, len); 2436 p = ngx_resolver_alloc(ctx->resolver, len);
2437 #endif
2159 if (p == NULL) { 2438 if (p == NULL) {
2160 return NGX_ERROR; 2439 return NGX_ERROR;
2161 } 2440 }
2162 2441
2163 rn->qlen = (u_short) len; 2442 rn->qlen = (u_short) len;
2164 rn->query = p; 2443 rn->query = p;
2165 2444
2445 #if (NGX_HAVE_INET6)
2446 rn->query6 = p + len;
2447 #endif
2448
2166 query = (ngx_resolver_hdr_t *) p; 2449 query = (ngx_resolver_hdr_t *) p;
2167 2450
2168 ident = ngx_random(); 2451 ident = ngx_random();
2169 2452
2170 ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, 2453 ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0,
2171 "resolve: \"%V\" %i", &ctx->name, ident & 0xffff); 2454 "resolve: \"%V\" A %i", &ctx->name, ident & 0xffff);
2172 2455
2173 query->ident_hi = (u_char) ((ident >> 8) & 0xff); 2456 query->ident_hi = (u_char) ((ident >> 8) & 0xff);
2174 query->ident_lo = (u_char) (ident & 0xff); 2457 query->ident_lo = (u_char) (ident & 0xff);
2175 2458
2176 /* recursion query */ 2459 /* recursion query */
2185 p += sizeof(ngx_resolver_hdr_t) + nlen; 2468 p += sizeof(ngx_resolver_hdr_t) + nlen;
2186 2469
2187 qs = (ngx_resolver_qs_t *) p; 2470 qs = (ngx_resolver_qs_t *) p;
2188 2471
2189 /* query type */ 2472 /* query type */
2190 qs->type_hi = 0; qs->type_lo = (u_char) ctx->type; 2473 qs->type_hi = 0; qs->type_lo = NGX_RESOLVE_A;
2191 2474
2192 /* IN query class */ 2475 /* IN query class */
2193 qs->class_hi = 0; qs->class_lo = 1; 2476 qs->class_hi = 0; qs->class_lo = 1;
2194 2477
2195 /* convert "www.example.com" to "\3www\7example\3com\0" */ 2478 /* convert "www.example.com" to "\3www\7example\3com\0" */
2222 if (len == 0 || len > 255) { 2505 if (len == 0 || len > 255) {
2223 return NGX_DECLINED; 2506 return NGX_DECLINED;
2224 } 2507 }
2225 2508
2226 *p = (u_char) len; 2509 *p = (u_char) len;
2510
2511 #if (NGX_HAVE_INET6)
2512 p = rn->query6;
2513
2514 ngx_memcpy(p, rn->query, rn->qlen);
2515
2516 query = (ngx_resolver_hdr_t *) p;
2517
2518 ident = ngx_random();
2519
2520 ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0,
2521 "resolve: \"%V\" AAAA %i", &ctx->name, ident & 0xffff);
2522
2523 query->ident_hi = (u_char) ((ident >> 8) & 0xff);
2524 query->ident_lo = (u_char) (ident & 0xff);
2525
2526 p += sizeof(ngx_resolver_hdr_t) + nlen;
2527
2528 qs = (ngx_resolver_qs_t *) p;
2529
2530 qs->type_lo = NGX_RESOLVE_AAAA;
2531 #endif
2227 2532
2228 return NGX_OK; 2533 return NGX_OK;
2229 } 2534 }
2230 2535
2231 2536
2447 2752
2448 if (rn->cnlen) { 2753 if (rn->cnlen) {
2449 ngx_resolver_free_locked(r, rn->u.cname); 2754 ngx_resolver_free_locked(r, rn->u.cname);
2450 } 2755 }
2451 2756
2452 if (rn->naddrs > 1) { 2757 if (rn->naddrs > 1 && rn->naddrs != (u_short) -1) {
2453 ngx_resolver_free_locked(r, rn->u.addrs); 2758 ngx_resolver_free_locked(r, rn->u.addrs);
2454 } 2759 }
2760
2761 #if (NGX_HAVE_INET6)
2762 if (rn->naddrs6 > 1 && rn->naddrs6 != (u_short) -1) {
2763 ngx_resolver_free_locked(r, rn->u6.addrs6);
2764 }
2765 #endif
2455 2766
2456 ngx_resolver_free_locked(r, rn); 2767 ngx_resolver_free_locked(r, rn);
2457 2768
2458 /* unlock alloc mutex */ 2769 /* unlock alloc mutex */
2459 } 2770 }
2523 return dst; 2834 return dst;
2524 } 2835 }
2525 2836
2526 2837
2527 static ngx_addr_t * 2838 static ngx_addr_t *
2528 ngx_resolver_export(ngx_resolver_t *r, in_addr_t *src, ngx_uint_t n, 2839 ngx_resolver_export(ngx_resolver_t *r, ngx_resolver_node_t *rn,
2529 ngx_uint_t rotate) 2840 ngx_uint_t rotate)
2530 { 2841 {
2531 ngx_addr_t *dst; 2842 ngx_addr_t *dst;
2532 ngx_uint_t i, j; 2843 ngx_uint_t d, i, j, n;
2533 struct sockaddr_in *sin; 2844 u_char (*sockaddr)[NGX_SOCKADDRLEN];
2845 in_addr_t *addr;
2846 struct sockaddr_in *sin;
2847 #if (NGX_HAVE_INET6)
2848 struct in6_addr *addr6;
2849 struct sockaddr_in6 *sin6;
2850 #endif
2851
2852 n = rn->naddrs;
2853 #if (NGX_HAVE_INET6)
2854 n += rn->naddrs6;
2855 #endif
2534 2856
2535 dst = ngx_resolver_calloc(r, n * sizeof(ngx_addr_t)); 2857 dst = ngx_resolver_calloc(r, n * sizeof(ngx_addr_t));
2536 if (dst == NULL) { 2858 if (dst == NULL) {
2537 return NULL; 2859 return NULL;
2538 } 2860 }
2539 2861
2540 sin = ngx_resolver_calloc(r, n * sizeof(struct sockaddr_in)); 2862 sockaddr = ngx_resolver_calloc(r, n * NGX_SOCKADDRLEN);
2541 2863 if (sockaddr == NULL) {
2542 if (sin == NULL) {
2543 ngx_resolver_free(r, dst); 2864 ngx_resolver_free(r, dst);
2544 return NULL; 2865 return NULL;
2545 } 2866 }
2546 2867
2547 j = rotate ? ngx_random() % n : 0; 2868 i = 0;
2548 2869 d = rotate ? ngx_random() % n : 0;
2549 for (i = 0; i < n; i++) { 2870
2550 dst[i].sockaddr = (struct sockaddr *) &sin[i]; 2871 if (rn->naddrs) {
2551 dst[i].socklen = sizeof(struct sockaddr_in); 2872 j = rotate ? ngx_random() % rn->naddrs : 0;
2552 sin[i].sin_family = AF_INET; 2873
2553 sin[i].sin_addr.s_addr = src[j++]; 2874 addr = (rn->naddrs == 1) ? &rn->u.addr : rn->u.addrs;
2554 2875
2555 if (j == n) { 2876 do {
2556 j = 0; 2877 sin = (struct sockaddr_in *) sockaddr[d];
2557 } 2878 sin->sin_family = AF_INET;
2558 } 2879 sin->sin_addr.s_addr = addr[j++];
2880 dst[d].sockaddr = (struct sockaddr *) sin;
2881 dst[d++].socklen = sizeof(struct sockaddr_in);
2882
2883 if (d == n) {
2884 d = 0;
2885 }
2886
2887 if (j == rn->naddrs) {
2888 j = 0;
2889 }
2890 } while (++i < rn->naddrs);
2891 }
2892
2893 #if (NGX_HAVE_INET6)
2894 if (rn->naddrs6) {
2895 j = rotate ? ngx_random() % rn->naddrs6 : 0;
2896
2897 addr6 = (rn->naddrs6 == 1) ? &rn->u6.addr6 : rn->u6.addrs6;
2898
2899 do {
2900 sin6 = (struct sockaddr_in6 *) sockaddr[d];
2901 sin6->sin6_family = AF_INET6;
2902 ngx_memcpy(sin6->sin6_addr.s6_addr, addr6[j++].s6_addr, 16);
2903 dst[d].sockaddr = (struct sockaddr *) sin6;
2904 dst[d++].socklen = sizeof(struct sockaddr_in6);
2905
2906 if (d == n) {
2907 d = 0;
2908 }
2909
2910 if (j == rn->naddrs6) {
2911 j = 0;
2912 }
2913 } while (++i < n);
2914 }
2915 #endif
2559 2916
2560 return dst; 2917 return dst;
2561 } 2918 }
2562 2919
2563 2920