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