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