comparison src/core/ngx_resolver.c @ 6458:384154fc634f

Resolver: added support for SRV records.
author Dmitry Volyntsev <xeioex@nginx.com>
date Wed, 23 Mar 2016 17:44:36 +0300
parents a6711b85da83
children 034329824dd3
comparison
equal deleted inserted replaced
6457:a6711b85da83 6458:384154fc634f
72 ngx_resolver_connection_t *rec, u_char *query, u_short qlen); 72 ngx_resolver_connection_t *rec, u_char *query, u_short qlen);
73 static ngx_int_t ngx_resolver_send_tcp_query(ngx_resolver_t *r, 73 static ngx_int_t ngx_resolver_send_tcp_query(ngx_resolver_t *r,
74 ngx_resolver_connection_t *rec, u_char *query, u_short qlen); 74 ngx_resolver_connection_t *rec, u_char *query, u_short qlen);
75 static ngx_int_t ngx_resolver_create_name_query(ngx_resolver_t *r, 75 static ngx_int_t ngx_resolver_create_name_query(ngx_resolver_t *r,
76 ngx_resolver_node_t *rn, ngx_str_t *name); 76 ngx_resolver_node_t *rn, ngx_str_t *name);
77 static ngx_int_t ngx_resolver_create_srv_query(ngx_resolver_t *r,
78 ngx_resolver_node_t *rn, ngx_str_t *name);
77 static ngx_int_t ngx_resolver_create_addr_query(ngx_resolver_t *r, 79 static ngx_int_t ngx_resolver_create_addr_query(ngx_resolver_t *r,
78 ngx_resolver_node_t *rn, ngx_addr_t *addr); 80 ngx_resolver_node_t *rn, ngx_resolver_addr_t *addr);
79 static void ngx_resolver_resend_handler(ngx_event_t *ev); 81 static void ngx_resolver_resend_handler(ngx_event_t *ev);
80 static time_t ngx_resolver_resend(ngx_resolver_t *r, ngx_rbtree_t *tree, 82 static time_t ngx_resolver_resend(ngx_resolver_t *r, ngx_rbtree_t *tree,
81 ngx_queue_t *queue); 83 ngx_queue_t *queue);
82 static ngx_uint_t ngx_resolver_resend_empty(ngx_resolver_t *r); 84 static ngx_uint_t ngx_resolver_resend_empty(ngx_resolver_t *r);
83 static void ngx_resolver_udp_read(ngx_event_t *rev); 85 static void ngx_resolver_udp_read(ngx_event_t *rev);
86 static void ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, 88 static void ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf,
87 size_t n, ngx_uint_t tcp); 89 size_t n, ngx_uint_t tcp);
88 static void ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n, 90 static void ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
89 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t qtype, 91 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t qtype,
90 ngx_uint_t nan, ngx_uint_t trunc, ngx_uint_t ans); 92 ngx_uint_t nan, ngx_uint_t trunc, ngx_uint_t ans);
93 static void ngx_resolver_process_srv(ngx_resolver_t *r, u_char *buf, size_t n,
94 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan,
95 ngx_uint_t trunc, ngx_uint_t ans);
91 static void ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n, 96 static void ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
92 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan); 97 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan);
93 static ngx_resolver_node_t *ngx_resolver_lookup_name(ngx_resolver_t *r, 98 static ngx_resolver_node_t *ngx_resolver_lookup_name(ngx_resolver_t *r,
99 ngx_str_t *name, uint32_t hash);
100 static ngx_resolver_node_t *ngx_resolver_lookup_srv(ngx_resolver_t *r,
94 ngx_str_t *name, uint32_t hash); 101 ngx_str_t *name, uint32_t hash);
95 static ngx_resolver_node_t *ngx_resolver_lookup_addr(ngx_resolver_t *r, 102 static ngx_resolver_node_t *ngx_resolver_lookup_addr(ngx_resolver_t *r,
96 in_addr_t addr); 103 in_addr_t addr);
97 static void ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp, 104 static void ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp,
98 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); 105 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
103 static void *ngx_resolver_alloc(ngx_resolver_t *r, size_t size); 110 static void *ngx_resolver_alloc(ngx_resolver_t *r, size_t size);
104 static void *ngx_resolver_calloc(ngx_resolver_t *r, size_t size); 111 static void *ngx_resolver_calloc(ngx_resolver_t *r, size_t size);
105 static void ngx_resolver_free(ngx_resolver_t *r, void *p); 112 static void ngx_resolver_free(ngx_resolver_t *r, void *p);
106 static void ngx_resolver_free_locked(ngx_resolver_t *r, void *p); 113 static void ngx_resolver_free_locked(ngx_resolver_t *r, void *p);
107 static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size); 114 static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size);
108 static ngx_addr_t *ngx_resolver_export(ngx_resolver_t *r, 115 static ngx_resolver_addr_t *ngx_resolver_export(ngx_resolver_t *r,
109 ngx_resolver_node_t *rn, ngx_uint_t rotate); 116 ngx_resolver_node_t *rn, ngx_uint_t rotate);
117 static void ngx_resolver_report_srv(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx);
110 static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len); 118 static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len);
119 static void ngx_resolver_resolve_srv_names(ngx_resolver_ctx_t *ctx,
120 ngx_resolver_node_t *rn);
121 static void ngx_resolver_srv_names_handler(ngx_resolver_ctx_t *ctx);
122 static ngx_int_t ngx_resolver_cmp_srvs(const void *one, const void *two);
111 123
112 #if (NGX_HAVE_INET6) 124 #if (NGX_HAVE_INET6)
113 static void ngx_resolver_rbtree_insert_addr6_value(ngx_rbtree_node_t *temp, 125 static void ngx_resolver_rbtree_insert_addr6_value(ngx_rbtree_node_t *temp,
114 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); 126 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
115 static ngx_resolver_node_t *ngx_resolver_lookup_addr6(ngx_resolver_t *r, 127 static ngx_resolver_node_t *ngx_resolver_lookup_addr6(ngx_resolver_t *r,
147 } 159 }
148 160
149 ngx_rbtree_init(&r->name_rbtree, &r->name_sentinel, 161 ngx_rbtree_init(&r->name_rbtree, &r->name_sentinel,
150 ngx_resolver_rbtree_insert_value); 162 ngx_resolver_rbtree_insert_value);
151 163
164 ngx_rbtree_init(&r->srv_rbtree, &r->srv_sentinel,
165 ngx_resolver_rbtree_insert_value);
166
152 ngx_rbtree_init(&r->addr_rbtree, &r->addr_sentinel, 167 ngx_rbtree_init(&r->addr_rbtree, &r->addr_sentinel,
153 ngx_rbtree_insert_value); 168 ngx_rbtree_insert_value);
154 169
155 ngx_queue_init(&r->name_resend_queue); 170 ngx_queue_init(&r->name_resend_queue);
171 ngx_queue_init(&r->srv_resend_queue);
156 ngx_queue_init(&r->addr_resend_queue); 172 ngx_queue_init(&r->addr_resend_queue);
157 173
158 ngx_queue_init(&r->name_expire_queue); 174 ngx_queue_init(&r->name_expire_queue);
175 ngx_queue_init(&r->srv_expire_queue);
159 ngx_queue_init(&r->addr_expire_queue); 176 ngx_queue_init(&r->addr_expire_queue);
160 177
161 #if (NGX_HAVE_INET6) 178 #if (NGX_HAVE_INET6)
162 r->ipv6 = 1; 179 r->ipv6 = 1;
163 180
271 if (r) { 288 if (r) {
272 ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, 289 ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
273 "cleanup resolver"); 290 "cleanup resolver");
274 291
275 ngx_resolver_cleanup_tree(r, &r->name_rbtree); 292 ngx_resolver_cleanup_tree(r, &r->name_rbtree);
293
294 ngx_resolver_cleanup_tree(r, &r->srv_rbtree);
276 295
277 ngx_resolver_cleanup_tree(r, &r->addr_rbtree); 296 ngx_resolver_cleanup_tree(r, &r->addr_rbtree);
278 297
279 #if (NGX_HAVE_INET6) 298 #if (NGX_HAVE_INET6)
280 ngx_resolver_cleanup_tree(r, &r->addr6_rbtree); 299 ngx_resolver_cleanup_tree(r, &r->addr6_rbtree);
381 400
382 401
383 ngx_int_t 402 ngx_int_t
384 ngx_resolve_name(ngx_resolver_ctx_t *ctx) 403 ngx_resolve_name(ngx_resolver_ctx_t *ctx)
385 { 404 {
405 size_t slen;
386 ngx_int_t rc; 406 ngx_int_t rc;
407 ngx_str_t name;
387 ngx_resolver_t *r; 408 ngx_resolver_t *r;
388 409
389 r = ctx->resolver; 410 r = ctx->resolver;
390 411
391 if (ctx->name.len > 0 && ctx->name.data[ctx->name.len - 1] == '.') { 412 if (ctx->name.len > 0 && ctx->name.data[ctx->name.len - 1] == '.') {
398 if (ctx->quick) { 419 if (ctx->quick) {
399 ctx->handler(ctx); 420 ctx->handler(ctx);
400 return NGX_OK; 421 return NGX_OK;
401 } 422 }
402 423
403 /* lock name mutex */ 424 if (ctx->service.len) {
404 425 slen = ctx->service.len;
405 rc = ngx_resolve_name_locked(r, ctx, &ctx->name); 426
427 if (ngx_strlchr(ctx->service.data,
428 ctx->service.data + ctx->service.len, '.')
429 == NULL)
430 {
431 slen += sizeof("_._tcp") - 1;
432 }
433
434 name.len = slen + 1 + ctx->name.len;
435
436 name.data = ngx_resolver_alloc(r, name.len);
437 if (name.data == NULL) {
438 return NGX_ERROR;
439 }
440
441 if (slen == ctx->service.len) {
442 ngx_sprintf(name.data, "%V.%V", &ctx->service, &ctx->name);
443
444 } else {
445 ngx_sprintf(name.data, "_%V._tcp.%V", &ctx->service, &ctx->name);
446 }
447
448 /* lock name mutex */
449
450 rc = ngx_resolve_name_locked(r, ctx, &name);
451
452 ngx_resolver_free(r, name.data);
453
454 } else {
455 /* lock name mutex */
456
457 rc = ngx_resolve_name_locked(r, ctx, &ctx->name);
458 }
406 459
407 if (rc == NGX_OK) { 460 if (rc == NGX_OK) {
408 return NGX_OK; 461 return NGX_OK;
409 } 462 }
410 463
427 480
428 481
429 void 482 void
430 ngx_resolve_name_done(ngx_resolver_ctx_t *ctx) 483 ngx_resolve_name_done(ngx_resolver_ctx_t *ctx)
431 { 484 {
485 ngx_uint_t i;
432 ngx_resolver_t *r; 486 ngx_resolver_t *r;
433 ngx_resolver_ctx_t *w, **p; 487 ngx_resolver_ctx_t *w, **p;
434 ngx_resolver_node_t *rn; 488 ngx_resolver_node_t *rn;
435 489
436 r = ctx->resolver; 490 r = ctx->resolver;
446 ngx_del_timer(ctx->event); 500 ngx_del_timer(ctx->event);
447 } 501 }
448 502
449 /* lock name mutex */ 503 /* lock name mutex */
450 504
505 if (ctx->nsrvs) {
506 for (i = 0; i < ctx->nsrvs; i++) {
507 if (ctx->srvs[i].ctx) {
508 ngx_resolve_name_done(ctx->srvs[i].ctx);
509 }
510
511 if (ctx->srvs[i].addrs) {
512 ngx_resolver_free(r, ctx->srvs[i].addrs->sockaddr);
513 ngx_resolver_free(r, ctx->srvs[i].addrs);
514 }
515
516 ngx_resolver_free(r, ctx->srvs[i].name.data);
517 }
518
519 ngx_resolver_free(r, ctx->srvs);
520 }
521
451 if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) { 522 if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) {
452 523
453 rn = ctx->node; 524 rn = ctx->node;
454 525
455 if (rn) { 526 if (rn) {
464 } 535 }
465 536
466 p = &w->next; 537 p = &w->next;
467 w = w->next; 538 w = w->next;
468 } 539 }
469 } 540
470 541 ngx_log_error(NGX_LOG_ALERT, r->log, 0,
471 ngx_log_error(NGX_LOG_ALERT, r->log, 0, 542 "could not cancel %V resolving", &ctx->name);
472 "could not cancel %V resolving", &ctx->name); 543 }
473 } 544 }
474 545
475 done: 546 done:
476 547
477 ngx_resolver_expire(r, &r->name_rbtree, &r->name_expire_queue); 548 if (ctx->service.len) {
549 ngx_resolver_expire(r, &r->srv_rbtree, &r->srv_expire_queue);
550
551 } else {
552 ngx_resolver_expire(r, &r->name_rbtree, &r->name_expire_queue);
553 }
478 554
479 /* unlock name mutex */ 555 /* unlock name mutex */
480 556
481 /* lock alloc mutex */ 557 /* lock alloc mutex */
482 558
499 ngx_str_t *name) 575 ngx_str_t *name)
500 { 576 {
501 uint32_t hash; 577 uint32_t hash;
502 ngx_int_t rc; 578 ngx_int_t rc;
503 ngx_str_t cname; 579 ngx_str_t cname;
504 ngx_uint_t naddrs; 580 ngx_uint_t i, naddrs;
505 ngx_addr_t *addrs; 581 ngx_queue_t *resend_queue, *expire_queue;
582 ngx_rbtree_t *tree;
506 ngx_resolver_ctx_t *next, *last; 583 ngx_resolver_ctx_t *next, *last;
584 ngx_resolver_addr_t *addrs;
507 ngx_resolver_node_t *rn; 585 ngx_resolver_node_t *rn;
508 586
509 ngx_strlow(name->data, name->data, name->len); 587 ngx_strlow(name->data, name->data, name->len);
510 588
511 hash = ngx_crc32_short(name->data, name->len); 589 hash = ngx_crc32_short(name->data, name->len);
512 590
513 rn = ngx_resolver_lookup_name(r, name, hash); 591 if (ctx->service.len) {
592 rn = ngx_resolver_lookup_srv(r, name, hash);
593
594 tree = &r->srv_rbtree;
595 resend_queue = &r->srv_resend_queue;
596 expire_queue = &r->srv_expire_queue;
597
598 } else {
599 rn = ngx_resolver_lookup_name(r, name, hash);
600
601 tree = &r->name_rbtree;
602 resend_queue = &r->name_resend_queue;
603 expire_queue = &r->name_expire_queue;
604 }
514 605
515 if (rn) { 606 if (rn) {
516 607
517 /* ctx can be a list after NGX_RESOLVE_CNAME */ 608 /* ctx can be a list after NGX_RESOLVE_CNAME */
518 for (last = ctx; last->next; last = last->next); 609 for (last = ctx; last->next; last = last->next);
523 614
524 ngx_queue_remove(&rn->queue); 615 ngx_queue_remove(&rn->queue);
525 616
526 rn->expire = ngx_time() + r->expire; 617 rn->expire = ngx_time() + r->expire;
527 618
528 ngx_queue_insert_head(&r->name_expire_queue, &rn->queue); 619 ngx_queue_insert_head(expire_queue, &rn->queue);
529 620
530 naddrs = (rn->naddrs == (u_short) -1) ? 0 : rn->naddrs; 621 naddrs = (rn->naddrs == (u_short) -1) ? 0 : rn->naddrs;
531 #if (NGX_HAVE_INET6) 622 #if (NGX_HAVE_INET6)
532 naddrs += (rn->naddrs6 == (u_short) -1) ? 0 : rn->naddrs6; 623 naddrs += (rn->naddrs6 == (u_short) -1) ? 0 : rn->naddrs6;
533 #endif 624 #endif
579 } 670 }
580 671
581 return NGX_OK; 672 return NGX_OK;
582 } 673 }
583 674
675 if (rn->nsrvs) {
676 last->next = rn->waiting;
677 rn->waiting = NULL;
678
679 /* unlock name mutex */
680
681 do {
682 next = ctx->next;
683
684 ngx_resolver_resolve_srv_names(ctx, rn);
685
686 ctx = next;
687 } while (ctx);
688
689 return NGX_OK;
690 }
691
584 /* NGX_RESOLVE_CNAME */ 692 /* NGX_RESOLVE_CNAME */
585 693
586 if (ctx->recursion++ < NGX_RESOLVER_MAX_RECURSION) { 694 if (ctx->recursion++ < NGX_RESOLVER_MAX_RECURSION) {
587 695
588 cname.len = rn->cnlen; 696 cname.len = rn->cnlen;
661 if (rn->naddrs6 > 1 && rn->naddrs6 != (u_short) -1) { 769 if (rn->naddrs6 > 1 && rn->naddrs6 != (u_short) -1) {
662 ngx_resolver_free_locked(r, rn->u6.addrs6); 770 ngx_resolver_free_locked(r, rn->u6.addrs6);
663 } 771 }
664 #endif 772 #endif
665 773
774 if (rn->nsrvs) {
775 for (i = 0; i < rn->nsrvs; i++) {
776 if (rn->u.srvs[i].name.data) {
777 ngx_resolver_free_locked(r, rn->u.srvs[i].name.data);
778 }
779 }
780
781 ngx_resolver_free_locked(r, rn->u.srvs);
782 }
783
666 /* unlock alloc mutex */ 784 /* unlock alloc mutex */
667 785
668 } else { 786 } else {
669 787
670 rn = ngx_resolver_alloc(r, sizeof(ngx_resolver_node_t)); 788 rn = ngx_resolver_alloc(r, sizeof(ngx_resolver_node_t));
683 rn->query = NULL; 801 rn->query = NULL;
684 #if (NGX_HAVE_INET6) 802 #if (NGX_HAVE_INET6)
685 rn->query6 = NULL; 803 rn->query6 = NULL;
686 #endif 804 #endif
687 805
688 ngx_rbtree_insert(&r->name_rbtree, &rn->node); 806 ngx_rbtree_insert(tree, &rn->node);
689 } 807 }
690 808
691 rc = ngx_resolver_create_name_query(r, rn, name); 809 if (ctx->service.len) {
810 rc = ngx_resolver_create_srv_query(r, rn, name);
811
812 } else {
813 rc = ngx_resolver_create_name_query(r, rn, name);
814 }
692 815
693 if (rc == NGX_ERROR) { 816 if (rc == NGX_ERROR) {
694 goto failed; 817 goto failed;
695 } 818 }
696 819
697 if (rc == NGX_DECLINED) { 820 if (rc == NGX_DECLINED) {
698 ngx_rbtree_delete(&r->name_rbtree, &rn->node); 821 ngx_rbtree_delete(tree, &rn->node);
699 822
700 ngx_resolver_free(r, rn->query); 823 ngx_resolver_free(r, rn->query);
701 ngx_resolver_free(r, rn->name); 824 ngx_resolver_free(r, rn->name);
702 ngx_resolver_free(r, rn); 825 ngx_resolver_free(r, rn);
703 826
722 rn->tcp = 0; 845 rn->tcp = 0;
723 #if (NGX_HAVE_INET6) 846 #if (NGX_HAVE_INET6)
724 rn->naddrs6 = r->ipv6 ? (u_short) -1 : 0; 847 rn->naddrs6 = r->ipv6 ? (u_short) -1 : 0;
725 rn->tcp6 = 0; 848 rn->tcp6 = 0;
726 #endif 849 #endif
850 rn->nsrvs = 0;
727 851
728 if (ngx_resolver_send_query(r, rn) != NGX_OK) { 852 if (ngx_resolver_send_query(r, rn) != NGX_OK) {
729 goto failed; 853 goto failed;
730 } 854 }
731 855
741 ctx->ident = -1; 865 ctx->ident = -1;
742 866
743 ngx_add_timer(ctx->event, ctx->timeout); 867 ngx_add_timer(ctx->event, ctx->timeout);
744 } 868 }
745 869
746 if (ngx_queue_empty(&r->name_resend_queue)) { 870 if (ngx_queue_empty(resend_queue)) {
747 ngx_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000)); 871 ngx_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000));
748 } 872 }
749 873
750 rn->expire = ngx_time() + r->resend_timeout; 874 rn->expire = ngx_time() + r->resend_timeout;
751 875
752 ngx_queue_insert_head(&r->name_resend_queue, &rn->queue); 876 ngx_queue_insert_head(resend_queue, &rn->queue);
753 877
754 rn->code = 0; 878 rn->code = 0;
755 rn->cnlen = 0; 879 rn->cnlen = 0;
756 rn->valid = 0; 880 rn->valid = 0;
757 rn->ttl = NGX_MAX_UINT32_VALUE; 881 rn->ttl = NGX_MAX_UINT32_VALUE;
766 890
767 return NGX_AGAIN; 891 return NGX_AGAIN;
768 892
769 failed: 893 failed:
770 894
771 ngx_rbtree_delete(&r->name_rbtree, &rn->node); 895 ngx_rbtree_delete(tree, &rn->node);
772 896
773 if (rn->query) { 897 if (rn->query) {
774 ngx_resolver_free(r, rn->query); 898 ngx_resolver_free(r, rn->query);
775 } 899 }
776 900
944 rn->tcp = 0; 1068 rn->tcp = 0;
945 #if (NGX_HAVE_INET6) 1069 #if (NGX_HAVE_INET6)
946 rn->naddrs6 = (u_short) -1; 1070 rn->naddrs6 = (u_short) -1;
947 rn->tcp6 = 0; 1071 rn->tcp6 = 0;
948 #endif 1072 #endif
1073 rn->nsrvs = 0;
949 1074
950 if (ngx_resolver_send_query(r, rn) != NGX_OK) { 1075 if (ngx_resolver_send_query(r, rn) != NGX_OK) {
951 goto failed; 1076 goto failed;
952 } 1077 }
953 1078
1299 1424
1300 1425
1301 static void 1426 static void
1302 ngx_resolver_resend_handler(ngx_event_t *ev) 1427 ngx_resolver_resend_handler(ngx_event_t *ev)
1303 { 1428 {
1304 time_t timer, atimer, ntimer; 1429 time_t timer, atimer, stimer, ntimer;
1305 #if (NGX_HAVE_INET6) 1430 #if (NGX_HAVE_INET6)
1306 time_t a6timer; 1431 time_t a6timer;
1307 #endif 1432 #endif
1308 ngx_resolver_t *r; 1433 ngx_resolver_t *r;
1309 1434
1314 1439
1315 /* lock name mutex */ 1440 /* lock name mutex */
1316 1441
1317 ntimer = ngx_resolver_resend(r, &r->name_rbtree, &r->name_resend_queue); 1442 ntimer = ngx_resolver_resend(r, &r->name_rbtree, &r->name_resend_queue);
1318 1443
1444 stimer = ngx_resolver_resend(r, &r->srv_rbtree, &r->srv_resend_queue);
1445
1319 /* unlock name mutex */ 1446 /* unlock name mutex */
1320 1447
1321 /* lock addr mutex */ 1448 /* lock addr mutex */
1322 1449
1323 atimer = ngx_resolver_resend(r, &r->addr_rbtree, &r->addr_resend_queue); 1450 atimer = ngx_resolver_resend(r, &r->addr_rbtree, &r->addr_resend_queue);
1339 if (timer == 0) { 1466 if (timer == 0) {
1340 timer = atimer; 1467 timer = atimer;
1341 1468
1342 } else if (atimer) { 1469 } else if (atimer) {
1343 timer = ngx_min(timer, atimer); 1470 timer = ngx_min(timer, atimer);
1471 }
1472
1473 if (timer == 0) {
1474 timer = stimer;
1475
1476 } else if (stimer) {
1477 timer = ngx_min(timer, stimer);
1344 } 1478 }
1345 1479
1346 #if (NGX_HAVE_INET6) 1480 #if (NGX_HAVE_INET6)
1347 1481
1348 if (timer == 0) { 1482 if (timer == 0) {
1701 ngx_resolver_process_a(r, buf, n, ident, code, qtype, nan, trunc, 1835 ngx_resolver_process_a(r, buf, n, ident, code, qtype, nan, trunc,
1702 i + sizeof(ngx_resolver_qs_t)); 1836 i + sizeof(ngx_resolver_qs_t));
1703 1837
1704 break; 1838 break;
1705 1839
1840 case NGX_RESOLVE_SRV:
1841
1842 ngx_resolver_process_srv(r, buf, n, ident, code, nan, trunc,
1843 i + sizeof(ngx_resolver_qs_t));
1844
1845 break;
1846
1706 case NGX_RESOLVE_PTR: 1847 case NGX_RESOLVE_PTR:
1707 1848
1708 ngx_resolver_process_ptr(r, buf, n, ident, code, nan); 1849 ngx_resolver_process_ptr(r, buf, n, ident, code, nan);
1709 1850
1710 break; 1851 break;
1754 size_t len; 1895 size_t len;
1755 int32_t ttl; 1896 int32_t ttl;
1756 uint32_t hash; 1897 uint32_t hash;
1757 in_addr_t *addr; 1898 in_addr_t *addr;
1758 ngx_str_t name; 1899 ngx_str_t name;
1759 ngx_addr_t *addrs;
1760 ngx_uint_t type, class, qident, naddrs, a, i, j, start; 1900 ngx_uint_t type, class, qident, naddrs, a, i, j, start;
1761 #if (NGX_HAVE_INET6) 1901 #if (NGX_HAVE_INET6)
1762 struct in6_addr *addr6; 1902 struct in6_addr *addr6;
1763 #endif 1903 #endif
1764 ngx_resolver_an_t *an; 1904 ngx_resolver_an_t *an;
1765 ngx_resolver_ctx_t *ctx, *next; 1905 ngx_resolver_ctx_t *ctx, *next;
1766 ngx_resolver_node_t *rn; 1906 ngx_resolver_node_t *rn;
1907 ngx_resolver_addr_t *addrs;
1767 ngx_resolver_connection_t *rec; 1908 ngx_resolver_connection_t *rec;
1768 1909
1769 if (ngx_resolver_copy(r, &name, buf, 1910 if (ngx_resolver_copy(r, &name, buf,
1770 buf + sizeof(ngx_resolver_hdr_t), buf + n) 1911 buf + sizeof(ngx_resolver_hdr_t), buf + n)
1771 != NGX_OK) 1912 != NGX_OK)
2394 next: 2535 next:
2395 2536
2396 /* unlock name mutex */ 2537 /* unlock name mutex */
2397 2538
2398 return; 2539 return;
2540 }
2541
2542
2543 static void
2544 ngx_resolver_process_srv(ngx_resolver_t *r, u_char *buf, size_t n,
2545 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan,
2546 ngx_uint_t trunc, ngx_uint_t ans)
2547 {
2548 char *err;
2549 u_char *cname;
2550 size_t len;
2551 int32_t ttl;
2552 uint32_t hash;
2553 ngx_str_t name;
2554 ngx_uint_t type, qident, class, start, nsrvs, a, i, j;
2555 ngx_resolver_an_t *an;
2556 ngx_resolver_ctx_t *ctx, *next;
2557 ngx_resolver_srv_t *srvs;
2558 ngx_resolver_node_t *rn;
2559 ngx_resolver_connection_t *rec;
2560
2561 if (ngx_resolver_copy(r, &name, buf,
2562 buf + sizeof(ngx_resolver_hdr_t), buf + n)
2563 != NGX_OK)
2564 {
2565 return;
2566 }
2567
2568 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver qs:%V", &name);
2569
2570 hash = ngx_crc32_short(name.data, name.len);
2571
2572 rn = ngx_resolver_lookup_srv(r, &name, hash);
2573
2574 if (rn == NULL || rn->query == NULL) {
2575 ngx_log_error(r->log_level, r->log, 0,
2576 "unexpected response for %V", &name);
2577 ngx_resolver_free(r, name.data);
2578 goto failed;
2579 }
2580
2581 if (trunc && rn->tcp) {
2582 ngx_resolver_free(r, name.data);
2583 goto failed;
2584 }
2585
2586 qident = (rn->query[0] << 8) + rn->query[1];
2587
2588 if (ident != qident) {
2589 ngx_log_error(r->log_level, r->log, 0,
2590 "wrong ident %ui response for %V, expect %ui",
2591 ident, &name, qident);
2592 ngx_resolver_free(r, name.data);
2593 goto failed;
2594 }
2595
2596 ngx_resolver_free(r, name.data);
2597
2598 if (trunc) {
2599
2600 ngx_queue_remove(&rn->queue);
2601
2602 if (rn->waiting == NULL) {
2603 ngx_rbtree_delete(&r->srv_rbtree, &rn->node);
2604 ngx_resolver_free_node(r, rn);
2605 return;
2606 }
2607
2608 rec = r->connections.elts;
2609 rec = &rec[rn->last_connection];
2610
2611 rn->tcp = 1;
2612
2613 (void) ngx_resolver_send_tcp_query(r, rec, rn->query, rn->qlen);
2614
2615 rn->expire = ngx_time() + r->resend_timeout;
2616
2617 ngx_queue_insert_head(&r->srv_resend_queue, &rn->queue);
2618
2619 return;
2620 }
2621
2622 if (code == 0 && rn->code) {
2623 code = rn->code;
2624 }
2625
2626 if (code == 0 && nan == 0) {
2627 code = NGX_RESOLVE_NXDOMAIN;
2628 }
2629
2630 if (code) {
2631 next = rn->waiting;
2632 rn->waiting = NULL;
2633
2634 ngx_queue_remove(&rn->queue);
2635
2636 ngx_rbtree_delete(&r->srv_rbtree, &rn->node);
2637
2638 while (next) {
2639 ctx = next;
2640 ctx->state = code;
2641 ctx->valid = ngx_time() + (r->valid ? r->valid : 10);
2642 next = ctx->next;
2643
2644 ctx->handler(ctx);
2645 }
2646
2647 ngx_resolver_free_node(r, rn);
2648
2649 return;
2650 }
2651
2652 i = ans;
2653 nsrvs = 0;
2654 cname = NULL;
2655
2656 for (a = 0; a < nan; a++) {
2657
2658 start = i;
2659
2660 while (i < n) {
2661
2662 if (buf[i] & 0xc0) {
2663 i += 2;
2664 goto found;
2665 }
2666
2667 if (buf[i] == 0) {
2668 i++;
2669 goto test_length;
2670 }
2671
2672 i += 1 + buf[i];
2673 }
2674
2675 goto short_response;
2676
2677 test_length:
2678
2679 if (i - start < 2) {
2680 err = "invalid name DNS response";
2681 goto invalid;
2682 }
2683
2684 found:
2685
2686 if (i + sizeof(ngx_resolver_an_t) >= n) {
2687 goto short_response;
2688 }
2689
2690 an = (ngx_resolver_an_t *) &buf[i];
2691
2692 type = (an->type_hi << 8) + an->type_lo;
2693 class = (an->class_hi << 8) + an->class_lo;
2694 len = (an->len_hi << 8) + an->len_lo;
2695 ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16)
2696 + (an->ttl[2] << 8) + (an->ttl[3]);
2697
2698 if (class != 1) {
2699 ngx_log_error(r->log_level, r->log, 0,
2700 "unexpected RR class %ui", class);
2701 goto failed;
2702 }
2703
2704 if (ttl < 0) {
2705 ttl = 0;
2706 }
2707
2708 rn->ttl = ngx_min(rn->ttl, (uint32_t) ttl);
2709
2710 i += sizeof(ngx_resolver_an_t);
2711
2712 switch (type) {
2713
2714 case NGX_RESOLVE_SRV:
2715
2716 if (i + 6 > n) {
2717 goto short_response;
2718 }
2719
2720 if (ngx_resolver_copy(r, NULL, buf, &buf[i + 6], buf + n)
2721 != NGX_OK)
2722 {
2723 goto failed;
2724 }
2725
2726 nsrvs++;
2727
2728 break;
2729
2730 case NGX_RESOLVE_CNAME:
2731
2732 cname = &buf[i];
2733
2734 break;
2735
2736 case NGX_RESOLVE_DNAME:
2737
2738 break;
2739
2740 default:
2741
2742 ngx_log_error(r->log_level, r->log, 0,
2743 "unexpected RR type %ui", type);
2744 }
2745
2746 i += len;
2747 }
2748
2749 ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
2750 "resolver nsrvs:%ui cname:%p ttl:%uD",
2751 nsrvs, cname, rn->ttl);
2752
2753 if (nsrvs) {
2754
2755 srvs = ngx_resolver_calloc(r, nsrvs * sizeof(ngx_resolver_srv_t));
2756 if (srvs == NULL) {
2757 goto failed;
2758 }
2759
2760 rn->u.srvs = srvs;
2761 rn->nsrvs = nsrvs;
2762
2763 j = 0;
2764 i = ans;
2765
2766 for (a = 0; a < nan; a++) {
2767
2768 for ( ;; ) {
2769
2770 if (buf[i] & 0xc0) {
2771 i += 2;
2772 break;
2773 }
2774
2775 if (buf[i] == 0) {
2776 i++;
2777 break;
2778 }
2779
2780 i += 1 + buf[i];
2781 }
2782
2783 an = (ngx_resolver_an_t *) &buf[i];
2784
2785 type = (an->type_hi << 8) + an->type_lo;
2786 len = (an->len_hi << 8) + an->len_lo;
2787
2788 i += sizeof(ngx_resolver_an_t);
2789
2790 if (type == NGX_RESOLVE_SRV) {
2791
2792 srvs[j].priority = (buf[i] << 8) + buf[i + 1];
2793 srvs[j].weight = (buf[i + 2] << 8) + buf[i + 3];
2794
2795 if (srvs[j].weight == 0) {
2796 srvs[j].weight = 1;
2797 }
2798
2799 srvs[j].port = (buf[i + 4] << 8) + buf[i + 5];
2800
2801 if (ngx_resolver_copy(r, &srvs[j].name, buf, &buf[i + 6],
2802 buf + n)
2803 != NGX_OK)
2804 {
2805 goto failed;
2806 }
2807
2808 j++;
2809 }
2810
2811 i += len;
2812 }
2813
2814 ngx_sort(srvs, nsrvs, sizeof(ngx_resolver_srv_t),
2815 ngx_resolver_cmp_srvs);
2816
2817 ngx_resolver_free(r, rn->query);
2818 rn->query = NULL;
2819
2820 ngx_queue_remove(&rn->queue);
2821
2822 rn->valid = ngx_time() + (r->valid ? r->valid : (time_t) rn->ttl);
2823 rn->expire = ngx_time() + r->expire;
2824
2825 ngx_queue_insert_head(&r->srv_expire_queue, &rn->queue);
2826
2827 next = rn->waiting;
2828 rn->waiting = NULL;
2829
2830 while (next) {
2831 ctx = next;
2832 next = ctx->next;
2833
2834 ngx_resolver_resolve_srv_names(ctx, rn);
2835 }
2836
2837 return;
2838 }
2839
2840 rn->nsrvs = 0;
2841
2842 if (cname) {
2843
2844 /* CNAME only */
2845
2846 if (ngx_resolver_copy(r, &name, buf, cname, buf + n) != NGX_OK) {
2847 goto failed;
2848 }
2849
2850 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
2851 "resolver cname:\"%V\"", &name);
2852
2853 ngx_queue_remove(&rn->queue);
2854
2855 rn->cnlen = (u_short) name.len;
2856 rn->u.cname = name.data;
2857
2858 rn->valid = ngx_time() + (r->valid ? r->valid : (time_t) rn->ttl);
2859 rn->expire = ngx_time() + r->expire;
2860
2861 ngx_queue_insert_head(&r->srv_expire_queue, &rn->queue);
2862
2863 ngx_resolver_free(r, rn->query);
2864 rn->query = NULL;
2865 #if (NGX_HAVE_INET6)
2866 rn->query6 = NULL;
2867 #endif
2868
2869 ctx = rn->waiting;
2870 rn->waiting = NULL;
2871
2872 if (ctx) {
2873
2874 if (ctx->recursion++ >= NGX_RESOLVER_MAX_RECURSION) {
2875
2876 /* unlock name mutex */
2877
2878 do {
2879 ctx->state = NGX_RESOLVE_NXDOMAIN;
2880 next = ctx->next;
2881
2882 ctx->handler(ctx);
2883
2884 ctx = next;
2885 } while (ctx);
2886
2887 return;
2888 }
2889
2890 for (next = ctx; next; next = next->next) {
2891 next->node = NULL;
2892 }
2893
2894 (void) ngx_resolve_name_locked(r, ctx, &name);
2895 }
2896
2897 /* unlock name mutex */
2898
2899 return;
2900 }
2901
2902 ngx_log_error(r->log_level, r->log, 0, "no SRV type in DNS response");
2903
2904 return;
2905
2906 short_response:
2907
2908 err = "short DNS response";
2909
2910 invalid:
2911
2912 /* unlock name mutex */
2913
2914 ngx_log_error(r->log_level, r->log, 0, err);
2915
2916 return;
2917
2918 failed:
2919
2920 /* unlock name mutex */
2921
2922 return;
2923 }
2924
2925
2926 static void
2927 ngx_resolver_resolve_srv_names(ngx_resolver_ctx_t *ctx, ngx_resolver_node_t *rn)
2928 {
2929 ngx_uint_t i;
2930 ngx_resolver_t *r;
2931 ngx_resolver_ctx_t *cctx;
2932 ngx_resolver_srv_name_t *srvs;
2933
2934 r = ctx->resolver;
2935
2936 ctx->node = NULL;
2937 ctx->state = NGX_OK;
2938 ctx->valid = rn->valid;
2939 ctx->count = rn->nsrvs;
2940
2941 srvs = ngx_resolver_calloc(r, rn->nsrvs * sizeof(ngx_resolver_srv_name_t));
2942 if (srvs == NULL) {
2943 goto failed;
2944 }
2945
2946 ctx->srvs = srvs;
2947 ctx->nsrvs = rn->nsrvs;
2948
2949 for (i = 0; i < rn->nsrvs; i++) {
2950 srvs[i].name.data = ngx_resolver_alloc(r, rn->u.srvs[i].name.len);
2951 if (srvs[i].name.data == NULL) {
2952 goto failed;
2953 }
2954
2955 srvs[i].name.len = rn->u.srvs[i].name.len;
2956 ngx_memcpy(srvs[i].name.data, rn->u.srvs[i].name.data,
2957 srvs[i].name.len);
2958
2959 cctx = ngx_resolve_start(r, NULL);
2960 if (cctx == NULL) {
2961 goto failed;
2962 }
2963
2964 cctx->name = srvs[i].name;
2965 cctx->handler = ngx_resolver_srv_names_handler;
2966 cctx->data = ctx;
2967 cctx->srvs = &srvs[i];
2968 cctx->timeout = 0;
2969
2970 srvs[i].priority = rn->u.srvs[i].priority;
2971 srvs[i].weight = rn->u.srvs[i].weight;
2972 srvs[i].port = rn->u.srvs[i].port;
2973 srvs[i].ctx = cctx;
2974
2975 if (ngx_resolve_name(cctx) == NGX_ERROR) {
2976 srvs[i].ctx = NULL;
2977 goto failed;
2978 }
2979 }
2980
2981 return;
2982
2983 failed:
2984
2985 ctx->state = NGX_ERROR;
2986 ctx->valid = ngx_time() + (r->valid ? r->valid : 10);
2987
2988 ctx->handler(ctx);
2989 }
2990
2991
2992 static void
2993 ngx_resolver_srv_names_handler(ngx_resolver_ctx_t *cctx)
2994 {
2995 ngx_uint_t i;
2996 u_char (*sockaddr)[NGX_SOCKADDRLEN];
2997 ngx_addr_t *addrs;
2998 ngx_resolver_t *r;
2999 struct sockaddr_in *sin;
3000 ngx_resolver_ctx_t *ctx;
3001 ngx_resolver_srv_name_t *srv;
3002 #if (NGX_HAVE_INET6)
3003 struct sockaddr_in6 *sin6;
3004 #endif
3005
3006 r = cctx->resolver;
3007 ctx = cctx->data;
3008 srv = cctx->srvs;
3009
3010 ctx->count--;
3011
3012 srv->ctx = NULL;
3013
3014 if (cctx->naddrs) {
3015
3016 ctx->valid = ngx_min(ctx->valid, cctx->valid);
3017
3018 addrs = ngx_resolver_calloc(r, cctx->naddrs * sizeof(ngx_addr_t));
3019 if (addrs == NULL) {
3020 ngx_resolve_name_done(cctx);
3021
3022 ctx->state = NGX_ERROR;
3023 ctx->valid = ngx_time() + (r->valid ? r->valid : 10);
3024
3025 ctx->handler(ctx);
3026 return;
3027 }
3028
3029 sockaddr = ngx_resolver_alloc(r, cctx->naddrs * NGX_SOCKADDRLEN);
3030 if (sockaddr == NULL) {
3031 ngx_resolver_free(r, addrs);
3032 ngx_resolve_name_done(cctx);
3033
3034 ctx->state = NGX_ERROR;
3035 ctx->valid = ngx_time() + (r->valid ? r->valid : 10);
3036
3037 ctx->handler(ctx);
3038 return;
3039 }
3040
3041 for (i = 0; i < cctx->naddrs; i++) {
3042 addrs[i].sockaddr = (struct sockaddr *) sockaddr[i];
3043 addrs[i].socklen = cctx->addrs[i].socklen;
3044
3045 ngx_memcpy(sockaddr[i], cctx->addrs[i].sockaddr,
3046 addrs[i].socklen);
3047
3048 switch (addrs[i].sockaddr->sa_family) {
3049 #if (NGX_HAVE_INET6)
3050 case AF_INET6:
3051 sin6 = (struct sockaddr_in6 *) addrs[i].sockaddr;
3052 sin6->sin6_port = htons(srv->port);
3053 break;
3054 #endif
3055 default: /* AF_INET */
3056 sin = (struct sockaddr_in *) addrs[i].sockaddr;
3057 sin->sin_port = htons(srv->port);
3058 }
3059 }
3060
3061 srv->addrs = addrs;
3062 srv->naddrs = cctx->naddrs;
3063 }
3064
3065 ngx_resolve_name_done(cctx);
3066
3067 if (ctx->count == 0) {
3068 ngx_resolver_report_srv(r, ctx);
3069 }
2399 } 3070 }
2400 3071
2401 3072
2402 static void 3073 static void
2403 ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n, 3074 ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
2756 return NULL; 3427 return NULL;
2757 } 3428 }
2758 3429
2759 3430
2760 static ngx_resolver_node_t * 3431 static ngx_resolver_node_t *
3432 ngx_resolver_lookup_srv(ngx_resolver_t *r, ngx_str_t *name, uint32_t hash)
3433 {
3434 ngx_int_t rc;
3435 ngx_rbtree_node_t *node, *sentinel;
3436 ngx_resolver_node_t *rn;
3437
3438 node = r->srv_rbtree.root;
3439 sentinel = r->srv_rbtree.sentinel;
3440
3441 while (node != sentinel) {
3442
3443 if (hash < node->key) {
3444 node = node->left;
3445 continue;
3446 }
3447
3448 if (hash > node->key) {
3449 node = node->right;
3450 continue;
3451 }
3452
3453 /* hash == node->key */
3454
3455 rn = ngx_resolver_node(node);
3456
3457 rc = ngx_memn2cmp(name->data, rn->name, name->len, rn->nlen);
3458
3459 if (rc == 0) {
3460 return rn;
3461 }
3462
3463 node = (rc < 0) ? node->left : node->right;
3464 }
3465
3466 /* not found */
3467
3468 return NULL;
3469 }
3470
3471
3472 static ngx_resolver_node_t *
2761 ngx_resolver_lookup_addr(ngx_resolver_t *r, in_addr_t addr) 3473 ngx_resolver_lookup_addr(ngx_resolver_t *r, in_addr_t addr)
2762 { 3474 {
2763 ngx_rbtree_node_t *node, *sentinel; 3475 ngx_rbtree_node_t *node, *sentinel;
2764 3476
2765 node = r->addr_rbtree.root; 3477 node = r->addr_rbtree.root;
3043 return NGX_OK; 3755 return NGX_OK;
3044 } 3756 }
3045 3757
3046 3758
3047 static ngx_int_t 3759 static ngx_int_t
3760 ngx_resolver_create_srv_query(ngx_resolver_t *r, ngx_resolver_node_t *rn,
3761 ngx_str_t *name)
3762 {
3763 u_char *p, *s;
3764 size_t len, nlen;
3765 ngx_uint_t ident;
3766 ngx_resolver_qs_t *qs;
3767 ngx_resolver_hdr_t *query;
3768
3769 nlen = name->len ? (1 + name->len + 1) : 1;
3770
3771 len = sizeof(ngx_resolver_hdr_t) + nlen + sizeof(ngx_resolver_qs_t);
3772
3773 p = ngx_resolver_alloc(r, len);
3774 if (p == NULL) {
3775 return NGX_ERROR;
3776 }
3777
3778 rn->qlen = (u_short) len;
3779 rn->query = p;
3780
3781 query = (ngx_resolver_hdr_t *) p;
3782
3783 ident = ngx_random();
3784
3785 ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,
3786 "resolve: \"%V\" SRV %i", name, ident & 0xffff);
3787
3788 query->ident_hi = (u_char) ((ident >> 8) & 0xff);
3789 query->ident_lo = (u_char) (ident & 0xff);
3790
3791 /* recursion query */
3792 query->flags_hi = 1; query->flags_lo = 0;
3793
3794 /* one question */
3795 query->nqs_hi = 0; query->nqs_lo = 1;
3796 query->nan_hi = 0; query->nan_lo = 0;
3797 query->nns_hi = 0; query->nns_lo = 0;
3798 query->nar_hi = 0; query->nar_lo = 0;
3799
3800 p += sizeof(ngx_resolver_hdr_t) + nlen;
3801
3802 qs = (ngx_resolver_qs_t *) p;
3803
3804 /* query type */
3805 qs->type_hi = 0; qs->type_lo = NGX_RESOLVE_SRV;
3806
3807 /* IN query class */
3808 qs->class_hi = 0; qs->class_lo = 1;
3809
3810 /* converts "www.example.com" to "\3www\7example\3com\0" */
3811
3812 len = 0;
3813 p--;
3814 *p-- = '\0';
3815
3816 if (name->len == 0) {
3817 return NGX_DECLINED;
3818 }
3819
3820 for (s = name->data + name->len - 1; s >= name->data; s--) {
3821 if (*s != '.') {
3822 *p = *s;
3823 len++;
3824
3825 } else {
3826 if (len == 0 || len > 255) {
3827 return NGX_DECLINED;
3828 }
3829
3830 *p = (u_char) len;
3831 len = 0;
3832 }
3833
3834 p--;
3835 }
3836
3837 if (len == 0 || len > 255) {
3838 return NGX_DECLINED;
3839 }
3840
3841 *p = (u_char) len;
3842
3843 return NGX_OK;
3844 }
3845
3846
3847 static ngx_int_t
3048 ngx_resolver_create_addr_query(ngx_resolver_t *r, ngx_resolver_node_t *rn, 3848 ngx_resolver_create_addr_query(ngx_resolver_t *r, ngx_resolver_node_t *rn,
3049 ngx_addr_t *addr) 3849 ngx_resolver_addr_t *addr)
3050 { 3850 {
3051 u_char *p, *d; 3851 u_char *p, *d;
3052 size_t len; 3852 size_t len;
3053 in_addr_t inaddr; 3853 in_addr_t inaddr;
3054 ngx_int_t n; 3854 ngx_int_t n;
3248 4048
3249 4049
3250 static void 4050 static void
3251 ngx_resolver_free_node(ngx_resolver_t *r, ngx_resolver_node_t *rn) 4051 ngx_resolver_free_node(ngx_resolver_t *r, ngx_resolver_node_t *rn)
3252 { 4052 {
4053 ngx_uint_t i;
4054
3253 /* lock alloc mutex */ 4055 /* lock alloc mutex */
3254 4056
3255 if (rn->query) { 4057 if (rn->query) {
3256 ngx_resolver_free_locked(r, rn->query); 4058 ngx_resolver_free_locked(r, rn->query);
3257 } 4059 }
3272 if (rn->naddrs6 > 1 && rn->naddrs6 != (u_short) -1) { 4074 if (rn->naddrs6 > 1 && rn->naddrs6 != (u_short) -1) {
3273 ngx_resolver_free_locked(r, rn->u6.addrs6); 4075 ngx_resolver_free_locked(r, rn->u6.addrs6);
3274 } 4076 }
3275 #endif 4077 #endif
3276 4078
4079 if (rn->nsrvs) {
4080 for (i = 0; i < rn->nsrvs; i++) {
4081 if (rn->u.srvs[i].name.data) {
4082 ngx_resolver_free_locked(r, rn->u.srvs[i].name.data);
4083 }
4084 }
4085
4086 ngx_resolver_free_locked(r, rn->u.srvs);
4087 }
4088
3277 ngx_resolver_free_locked(r, rn); 4089 ngx_resolver_free_locked(r, rn);
3278 4090
3279 /* unlock alloc mutex */ 4091 /* unlock alloc mutex */
3280 } 4092 }
3281 4093
3343 4155
3344 return dst; 4156 return dst;
3345 } 4157 }
3346 4158
3347 4159
3348 static ngx_addr_t * 4160 static ngx_resolver_addr_t *
3349 ngx_resolver_export(ngx_resolver_t *r, ngx_resolver_node_t *rn, 4161 ngx_resolver_export(ngx_resolver_t *r, ngx_resolver_node_t *rn,
3350 ngx_uint_t rotate) 4162 ngx_uint_t rotate)
3351 { 4163 {
3352 ngx_addr_t *dst;
3353 ngx_uint_t d, i, j, n; 4164 ngx_uint_t d, i, j, n;
3354 u_char (*sockaddr)[NGX_SOCKADDRLEN]; 4165 u_char (*sockaddr)[NGX_SOCKADDRLEN];
3355 in_addr_t *addr; 4166 in_addr_t *addr;
3356 struct sockaddr_in *sin; 4167 struct sockaddr_in *sin;
4168 ngx_resolver_addr_t *dst;
3357 #if (NGX_HAVE_INET6) 4169 #if (NGX_HAVE_INET6)
3358 struct in6_addr *addr6; 4170 struct in6_addr *addr6;
3359 struct sockaddr_in6 *sin6; 4171 struct sockaddr_in6 *sin6;
3360 #endif 4172 #endif
3361 4173
3362 n = rn->naddrs; 4174 n = rn->naddrs;
3363 #if (NGX_HAVE_INET6) 4175 #if (NGX_HAVE_INET6)
3364 n += rn->naddrs6; 4176 n += rn->naddrs6;
3365 #endif 4177 #endif
3366 4178
3367 dst = ngx_resolver_calloc(r, n * sizeof(ngx_addr_t)); 4179 dst = ngx_resolver_calloc(r, n * sizeof(ngx_resolver_addr_t));
3368 if (dst == NULL) { 4180 if (dst == NULL) {
3369 return NULL; 4181 return NULL;
3370 } 4182 }
3371 4183
3372 sockaddr = ngx_resolver_calloc(r, n * NGX_SOCKADDRLEN); 4184 sockaddr = ngx_resolver_calloc(r, n * NGX_SOCKADDRLEN);
3423 } while (++i < n); 4235 } while (++i < n);
3424 } 4236 }
3425 #endif 4237 #endif
3426 4238
3427 return dst; 4239 return dst;
4240 }
4241
4242
4243 static void
4244 ngx_resolver_report_srv(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
4245 {
4246 u_short nsrvs;
4247 ngx_uint_t naddrs, nw, i, j, k, l, m, n, w;
4248 ngx_resolver_addr_t *addrs;
4249 ngx_resolver_srv_name_t *srvs;
4250
4251 naddrs = 0;
4252
4253 for (i = 0; i < ctx->nsrvs; i++) {
4254 naddrs += ctx->srvs[i].naddrs;
4255 }
4256
4257 if (naddrs == 0) {
4258 ctx->state = NGX_RESOLVE_NXDOMAIN;
4259 ctx->valid = ngx_time() + (r->valid ? r->valid : 10);
4260
4261 ctx->handler(ctx);
4262 return;
4263 }
4264
4265 addrs = ngx_resolver_calloc(r, naddrs * sizeof(ngx_resolver_addr_t));
4266 if (addrs == NULL) {
4267 ctx->state = NGX_ERROR;
4268 ctx->valid = ngx_time() + (r->valid ? r->valid : 10);
4269
4270 ctx->handler(ctx);
4271 return;
4272 }
4273
4274 srvs = ctx->srvs;
4275 nsrvs = ctx->nsrvs;
4276
4277 i = 0;
4278 n = 0;
4279
4280 do {
4281 nw = 0;
4282
4283 for (j = i; j < nsrvs; j++) {
4284 if (srvs[j].priority != srvs[i].priority) {
4285 break;
4286 }
4287
4288 nw += srvs[j].naddrs * srvs[j].weight;
4289 }
4290
4291 if (nw == 0) {
4292 goto next_srv;
4293 }
4294
4295 w = ngx_random() % nw;
4296
4297 for (k = i; k < j; k++) {
4298 if (w < srvs[k].naddrs * srvs[k].weight) {
4299 break;
4300 }
4301
4302 w -= srvs[k].naddrs * srvs[k].weight;
4303 }
4304
4305 for (l = i; l < j; l++) {
4306
4307 for (m = 0; m < srvs[k].naddrs; m++) {
4308 addrs[n].socklen = srvs[k].addrs[m].socklen;
4309 addrs[n].sockaddr = srvs[k].addrs[m].sockaddr;
4310 addrs[n].name = srvs[k].name;
4311 addrs[n].priority = srvs[k].priority;
4312 addrs[n].weight = srvs[k].weight;
4313 n++;
4314 }
4315
4316 if (++k == j) {
4317 k = i;
4318 }
4319 }
4320
4321 next_srv:
4322
4323 i = j;
4324
4325 } while (i < ctx->nsrvs);
4326
4327 ctx->state = NGX_OK;
4328 ctx->addrs = addrs;
4329 ctx->naddrs = naddrs;
4330
4331 ctx->handler(ctx);
4332
4333 ngx_resolver_free(r, addrs);
3428 } 4334 }
3429 4335
3430 4336
3431 char * 4337 char *
3432 ngx_resolver_strerror(ngx_int_t err) 4338 ngx_resolver_strerror(ngx_int_t err)
3737 ngx_close_connection(c); 4643 ngx_close_connection(c);
3738 rec->tcp = NULL; 4644 rec->tcp = NULL;
3739 4645
3740 return NGX_ERROR; 4646 return NGX_ERROR;
3741 } 4647 }
4648
4649
4650 static ngx_int_t
4651 ngx_resolver_cmp_srvs(const void *one, const void *two)
4652 {
4653 ngx_int_t p1, p2;
4654 ngx_resolver_srv_t *first, *second;
4655
4656 first = (ngx_resolver_srv_t *) one;
4657 second = (ngx_resolver_srv_t *) two;
4658
4659 p1 = first->priority;
4660 p2 = second->priority;
4661
4662 return p1 - p2;
4663 }