Mercurial > hg > nginx
comparison src/core/ngx_resolver.c @ 5476:950c9ed3e66f
Resolver: implemented IPv6 address to name resolving.
author | Ruslan Ermilov <ru@nginx.com> |
---|---|
date | Fri, 06 Dec 2013 14:30:28 +0400 |
parents | 07dd5bd222ac |
children | 98876ce2a7fd |
comparison
equal
deleted
inserted
replaced
5475:07dd5bd222ac | 5476:950c9ed3e66f |
---|---|
90 static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size); | 90 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, | 91 static ngx_addr_t *ngx_resolver_export(ngx_resolver_t *r, in_addr_t *src, |
92 ngx_uint_t n, ngx_uint_t rotate); | 92 ngx_uint_t n, ngx_uint_t rotate); |
93 static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len); | 93 static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len); |
94 | 94 |
95 #if (NGX_HAVE_INET6) | |
96 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 static ngx_resolver_node_t *ngx_resolver_lookup_addr6(ngx_resolver_t *r, | |
99 struct in6_addr *addr, uint32_t hash); | |
100 #endif | |
101 | |
95 | 102 |
96 ngx_resolver_t * | 103 ngx_resolver_t * |
97 ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n) | 104 ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n) |
98 { | 105 { |
99 ngx_str_t s; | 106 ngx_str_t s; |
132 ngx_queue_init(&r->addr_resend_queue); | 139 ngx_queue_init(&r->addr_resend_queue); |
133 | 140 |
134 ngx_queue_init(&r->name_expire_queue); | 141 ngx_queue_init(&r->name_expire_queue); |
135 ngx_queue_init(&r->addr_expire_queue); | 142 ngx_queue_init(&r->addr_expire_queue); |
136 | 143 |
144 #if (NGX_HAVE_INET6) | |
145 ngx_rbtree_init(&r->addr6_rbtree, &r->addr6_sentinel, | |
146 ngx_resolver_rbtree_insert_addr6_value); | |
147 | |
148 ngx_queue_init(&r->addr6_resend_queue); | |
149 | |
150 ngx_queue_init(&r->addr6_expire_queue); | |
151 #endif | |
152 | |
137 r->event->handler = ngx_resolver_resend_handler; | 153 r->event->handler = ngx_resolver_resend_handler; |
138 r->event->data = r; | 154 r->event->data = r; |
139 r->event->log = &cf->cycle->new_log; | 155 r->event->log = &cf->cycle->new_log; |
140 r->ident = -1; | 156 r->ident = -1; |
141 | 157 |
217 "cleanup resolver"); | 233 "cleanup resolver"); |
218 | 234 |
219 ngx_resolver_cleanup_tree(r, &r->name_rbtree); | 235 ngx_resolver_cleanup_tree(r, &r->name_rbtree); |
220 | 236 |
221 ngx_resolver_cleanup_tree(r, &r->addr_rbtree); | 237 ngx_resolver_cleanup_tree(r, &r->addr_rbtree); |
238 | |
239 #if (NGX_HAVE_INET6) | |
240 ngx_resolver_cleanup_tree(r, &r->addr6_rbtree); | |
241 #endif | |
222 | 242 |
223 if (r->event) { | 243 if (r->event) { |
224 ngx_free(r->event); | 244 ngx_free(r->event); |
225 } | 245 } |
226 | 246 |
638 | 658 |
639 return NGX_ERROR; | 659 return NGX_ERROR; |
640 } | 660 } |
641 | 661 |
642 | 662 |
643 /* AF_INET only */ | |
644 | |
645 ngx_int_t | 663 ngx_int_t |
646 ngx_resolve_addr(ngx_resolver_ctx_t *ctx) | 664 ngx_resolve_addr(ngx_resolver_ctx_t *ctx) |
647 { | 665 { |
648 u_char *name; | 666 u_char *name; |
649 in_addr_t addr; | 667 in_addr_t addr; |
668 ngx_queue_t *resend_queue, *expire_queue; | |
669 ngx_rbtree_t *tree; | |
650 ngx_resolver_t *r; | 670 ngx_resolver_t *r; |
651 struct sockaddr_in *sin; | 671 struct sockaddr_in *sin; |
652 ngx_resolver_node_t *rn; | 672 ngx_resolver_node_t *rn; |
673 #if (NGX_HAVE_INET6) | |
674 uint32_t hash; | |
675 struct sockaddr_in6 *sin6; | |
676 #endif | |
677 | |
678 #if (NGX_SUPPRESS_WARN) | |
679 addr = 0; | |
680 #if (NGX_HAVE_INET6) | |
681 hash = 0; | |
682 sin6 = NULL; | |
683 #endif | |
684 #endif | |
653 | 685 |
654 r = ctx->resolver; | 686 r = ctx->resolver; |
655 | 687 |
656 if (ctx->addr.sockaddr->sa_family != AF_INET) { | 688 switch (ctx->addr.sockaddr->sa_family) { |
657 return NGX_ERROR; | 689 |
658 } | 690 #if (NGX_HAVE_INET6) |
659 | 691 case AF_INET6: |
660 sin = (struct sockaddr_in *) ctx->addr.sockaddr; | 692 sin6 = (struct sockaddr_in6 *) ctx->addr.sockaddr; |
661 addr = ntohl(sin->sin_addr.s_addr); | 693 hash = ngx_crc32_short(sin6->sin6_addr.s6_addr, 16); |
662 | 694 |
663 /* lock addr mutex */ | 695 /* lock addr mutex */ |
664 | 696 |
665 rn = ngx_resolver_lookup_addr(r, addr); | 697 rn = ngx_resolver_lookup_addr6(r, &sin6->sin6_addr, hash); |
698 | |
699 tree = &r->addr6_rbtree; | |
700 resend_queue = &r->addr6_resend_queue; | |
701 expire_queue = &r->addr6_expire_queue; | |
702 | |
703 break; | |
704 #endif | |
705 | |
706 default: /* AF_INET */ | |
707 sin = (struct sockaddr_in *) ctx->addr.sockaddr; | |
708 addr = ntohl(sin->sin_addr.s_addr); | |
709 | |
710 /* lock addr mutex */ | |
711 | |
712 rn = ngx_resolver_lookup_addr(r, addr); | |
713 | |
714 tree = &r->addr_rbtree; | |
715 resend_queue = &r->addr_resend_queue; | |
716 expire_queue = &r->addr_expire_queue; | |
717 } | |
666 | 718 |
667 if (rn) { | 719 if (rn) { |
668 | 720 |
669 if (rn->valid >= ngx_time()) { | 721 if (rn->valid >= ngx_time()) { |
670 | 722 |
672 | 724 |
673 ngx_queue_remove(&rn->queue); | 725 ngx_queue_remove(&rn->queue); |
674 | 726 |
675 rn->expire = ngx_time() + r->expire; | 727 rn->expire = ngx_time() + r->expire; |
676 | 728 |
677 ngx_queue_insert_head(&r->addr_expire_queue, &rn->queue); | 729 ngx_queue_insert_head(expire_queue, &rn->queue); |
678 | 730 |
679 name = ngx_resolver_dup(r, rn->name, rn->nlen); | 731 name = ngx_resolver_dup(r, rn->name, rn->nlen); |
680 if (name == NULL) { | 732 if (name == NULL) { |
681 goto failed; | 733 goto failed; |
682 } | 734 } |
715 rn = ngx_resolver_alloc(r, sizeof(ngx_resolver_node_t)); | 767 rn = ngx_resolver_alloc(r, sizeof(ngx_resolver_node_t)); |
716 if (rn == NULL) { | 768 if (rn == NULL) { |
717 goto failed; | 769 goto failed; |
718 } | 770 } |
719 | 771 |
720 rn->node.key = addr; | 772 switch (ctx->addr.sockaddr->sa_family) { |
773 | |
774 #if (NGX_HAVE_INET6) | |
775 case AF_INET6: | |
776 rn->addr6 = sin6->sin6_addr; | |
777 rn->node.key = hash; | |
778 break; | |
779 #endif | |
780 | |
781 default: /* AF_INET */ | |
782 rn->node.key = addr; | |
783 } | |
784 | |
721 rn->query = NULL; | 785 rn->query = NULL; |
722 | 786 |
723 ngx_rbtree_insert(&r->addr_rbtree, &rn->node); | 787 ngx_rbtree_insert(tree, &rn->node); |
724 } | 788 } |
725 | 789 |
726 if (ngx_resolver_create_addr_query(rn, ctx) != NGX_OK) { | 790 if (ngx_resolver_create_addr_query(rn, ctx) != NGX_OK) { |
727 goto failed; | 791 goto failed; |
728 } | 792 } |
741 ctx->event->log = r->log; | 805 ctx->event->log = r->log; |
742 ctx->ident = -1; | 806 ctx->ident = -1; |
743 | 807 |
744 ngx_add_timer(ctx->event, ctx->timeout); | 808 ngx_add_timer(ctx->event, ctx->timeout); |
745 | 809 |
746 if (ngx_queue_empty(&r->addr_resend_queue)) { | 810 if (ngx_queue_empty(resend_queue)) { |
747 ngx_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000)); | 811 ngx_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000)); |
748 } | 812 } |
749 | 813 |
750 rn->expire = ngx_time() + r->resend_timeout; | 814 rn->expire = ngx_time() + r->resend_timeout; |
751 | 815 |
752 ngx_queue_insert_head(&r->addr_resend_queue, &rn->queue); | 816 ngx_queue_insert_head(resend_queue, &rn->queue); |
753 | 817 |
754 rn->cnlen = 0; | 818 rn->cnlen = 0; |
755 rn->naddrs = 0; | 819 rn->naddrs = 0; |
756 rn->name = NULL; | 820 rn->name = NULL; |
757 rn->nlen = 0; | 821 rn->nlen = 0; |
765 return NGX_OK; | 829 return NGX_OK; |
766 | 830 |
767 failed: | 831 failed: |
768 | 832 |
769 if (rn) { | 833 if (rn) { |
770 ngx_rbtree_delete(&r->addr_rbtree, &rn->node); | 834 ngx_rbtree_delete(tree, &rn->node); |
771 | 835 |
772 if (rn->query) { | 836 if (rn->query) { |
773 ngx_resolver_free(r, rn->query); | 837 ngx_resolver_free(r, rn->query); |
774 } | 838 } |
775 | 839 |
786 | 850 |
787 return NGX_ERROR; | 851 return NGX_ERROR; |
788 } | 852 } |
789 | 853 |
790 | 854 |
791 /* AF_INET only */ | |
792 | |
793 void | 855 void |
794 ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx) | 856 ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx) |
795 { | 857 { |
796 in_addr_t addr; | 858 in_addr_t addr; |
859 ngx_queue_t *expire_queue; | |
860 ngx_rbtree_t *tree; | |
797 ngx_resolver_t *r; | 861 ngx_resolver_t *r; |
798 ngx_resolver_ctx_t *w, **p; | 862 ngx_resolver_ctx_t *w, **p; |
799 struct sockaddr_in *sin; | 863 struct sockaddr_in *sin; |
800 ngx_resolver_node_t *rn; | 864 ngx_resolver_node_t *rn; |
801 | 865 #if (NGX_HAVE_INET6) |
802 if (ctx->addr.sockaddr->sa_family != AF_INET) { | 866 uint32_t hash; |
803 return; | 867 struct sockaddr_in6 *sin6; |
804 } | 868 #endif |
805 | |
806 sin = (struct sockaddr_in *) ctx->addr.sockaddr; | |
807 addr = ntohl(sin->sin_addr.s_addr); | |
808 | 869 |
809 r = ctx->resolver; | 870 r = ctx->resolver; |
871 | |
872 switch (ctx->addr.sockaddr->sa_family) { | |
873 | |
874 #if (NGX_HAVE_INET6) | |
875 case AF_INET6: | |
876 tree = &r->addr6_rbtree; | |
877 expire_queue = &r->addr6_expire_queue; | |
878 break; | |
879 #endif | |
880 | |
881 default: /* AF_INET */ | |
882 tree = &r->addr_rbtree; | |
883 expire_queue = &r->addr_expire_queue; | |
884 } | |
810 | 885 |
811 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, | 886 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, |
812 "resolve addr done: %i", ctx->state); | 887 "resolve addr done: %i", ctx->state); |
813 | 888 |
814 if (ctx->event && ctx->event->timer_set) { | 889 if (ctx->event && ctx->event->timer_set) { |
817 | 892 |
818 /* lock addr mutex */ | 893 /* lock addr mutex */ |
819 | 894 |
820 if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) { | 895 if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) { |
821 | 896 |
822 rn = ngx_resolver_lookup_addr(r, addr); | 897 switch (ctx->addr.sockaddr->sa_family) { |
898 | |
899 #if (NGX_HAVE_INET6) | |
900 case AF_INET6: | |
901 sin6 = (struct sockaddr_in6 *) ctx->addr.sockaddr; | |
902 hash = ngx_crc32_short(sin6->sin6_addr.s6_addr, 16); | |
903 rn = ngx_resolver_lookup_addr6(r, &sin6->sin6_addr, hash); | |
904 break; | |
905 #endif | |
906 | |
907 default: /* AF_INET */ | |
908 sin = (struct sockaddr_in *) ctx->addr.sockaddr; | |
909 addr = ntohl(sin->sin_addr.s_addr); | |
910 rn = ngx_resolver_lookup_addr(r, addr); | |
911 } | |
823 | 912 |
824 if (rn) { | 913 if (rn) { |
825 p = &rn->waiting; | 914 p = &rn->waiting; |
826 w = rn->waiting; | 915 w = rn->waiting; |
827 | 916 |
835 p = &w->next; | 924 p = &w->next; |
836 w = w->next; | 925 w = w->next; |
837 } | 926 } |
838 } | 927 } |
839 | 928 |
840 ngx_log_error(NGX_LOG_ALERT, r->log, 0, | 929 { |
841 "could not cancel %ud.%ud.%ud.%ud resolving", | 930 u_char text[NGX_SOCKADDR_STRLEN]; |
842 (addr >> 24) & 0xff, (addr >> 16) & 0xff, | 931 ngx_str_t addrtext; |
843 (addr >> 8) & 0xff, addr & 0xff); | 932 |
933 addrtext.data = text; | |
934 addrtext.len = ngx_sock_ntop(ctx->addr.sockaddr, ctx->addr.socklen, | |
935 text, NGX_SOCKADDR_STRLEN, 0); | |
936 | |
937 ngx_log_error(NGX_LOG_ALERT, r->log, 0, | |
938 "could not cancel %V resolving", &addrtext); | |
939 } | |
844 } | 940 } |
845 | 941 |
846 done: | 942 done: |
847 | 943 |
848 ngx_resolver_expire(r, &r->addr_rbtree, &r->addr_expire_queue); | 944 ngx_resolver_expire(r, tree, expire_queue); |
849 | 945 |
850 /* unlock addr mutex */ | 946 /* unlock addr mutex */ |
851 | 947 |
852 /* lock alloc mutex */ | 948 /* lock alloc mutex */ |
853 | 949 |
944 | 1040 |
945 static void | 1041 static void |
946 ngx_resolver_resend_handler(ngx_event_t *ev) | 1042 ngx_resolver_resend_handler(ngx_event_t *ev) |
947 { | 1043 { |
948 time_t timer, atimer, ntimer; | 1044 time_t timer, atimer, ntimer; |
1045 #if (NGX_HAVE_INET6) | |
1046 time_t a6timer; | |
1047 #endif | |
949 ngx_resolver_t *r; | 1048 ngx_resolver_t *r; |
950 | 1049 |
951 r = ev->data; | 1050 r = ev->data; |
952 | 1051 |
953 ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0, | 1052 ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0, |
963 | 1062 |
964 atimer = ngx_resolver_resend(r, &r->addr_rbtree, &r->addr_resend_queue); | 1063 atimer = ngx_resolver_resend(r, &r->addr_rbtree, &r->addr_resend_queue); |
965 | 1064 |
966 /* unlock addr mutex */ | 1065 /* unlock addr mutex */ |
967 | 1066 |
968 if (ntimer == 0) { | 1067 #if (NGX_HAVE_INET6) |
1068 | |
1069 /* lock addr6 mutex */ | |
1070 | |
1071 a6timer = ngx_resolver_resend(r, &r->addr6_rbtree, &r->addr6_resend_queue); | |
1072 | |
1073 /* unlock addr6 mutex */ | |
1074 | |
1075 #endif | |
1076 | |
1077 timer = ntimer; | |
1078 | |
1079 if (timer == 0) { | |
969 timer = atimer; | 1080 timer = atimer; |
970 | 1081 |
971 } else if (atimer == 0) { | 1082 } else if (atimer) { |
972 timer = ntimer; | 1083 timer = ngx_min(timer, atimer); |
973 | 1084 } |
974 } else { | 1085 |
975 timer = (atimer < ntimer) ? atimer : ntimer; | 1086 #if (NGX_HAVE_INET6) |
976 } | 1087 |
1088 if (timer == 0) { | |
1089 timer = a6timer; | |
1090 | |
1091 } else if (a6timer) { | |
1092 timer = ngx_min(timer, a6timer); | |
1093 } | |
1094 | |
1095 #endif | |
977 | 1096 |
978 if (timer) { | 1097 if (timer) { |
979 ngx_add_timer(r->event, (ngx_msec_t) (timer * 1000)); | 1098 ngx_add_timer(r->event, (ngx_msec_t) (timer * 1000)); |
980 } | 1099 } |
981 } | 1100 } |
1553 ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n, | 1672 ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n, |
1554 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan) | 1673 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan) |
1555 { | 1674 { |
1556 char *err; | 1675 char *err; |
1557 size_t len; | 1676 size_t len; |
1677 u_char text[NGX_SOCKADDR_STRLEN]; | |
1558 in_addr_t addr; | 1678 in_addr_t addr; |
1559 int32_t ttl; | 1679 int32_t ttl; |
1560 ngx_int_t octet; | 1680 ngx_int_t octet; |
1561 ngx_str_t name; | 1681 ngx_str_t name; |
1562 ngx_uint_t i, mask, qident, class; | 1682 ngx_uint_t i, mask, qident, class; |
1683 ngx_queue_t *expire_queue; | |
1684 ngx_rbtree_t *tree; | |
1563 ngx_resolver_an_t *an; | 1685 ngx_resolver_an_t *an; |
1564 ngx_resolver_ctx_t *ctx, *next; | 1686 ngx_resolver_ctx_t *ctx, *next; |
1565 ngx_resolver_node_t *rn; | 1687 ngx_resolver_node_t *rn; |
1688 #if (NGX_HAVE_INET6) | |
1689 uint32_t hash; | |
1690 ngx_int_t digit; | |
1691 struct in6_addr addr6; | |
1692 #endif | |
1566 | 1693 |
1567 if (ngx_resolver_copy(r, NULL, buf, | 1694 if (ngx_resolver_copy(r, NULL, buf, |
1568 buf + sizeof(ngx_resolver_hdr_t), buf + n) | 1695 buf + sizeof(ngx_resolver_hdr_t), buf + n) |
1569 != NGX_OK) | 1696 != NGX_OK) |
1570 { | 1697 { |
1571 return; | 1698 return; |
1572 } | 1699 } |
1573 | 1700 |
1701 /* AF_INET */ | |
1702 | |
1574 addr = 0; | 1703 addr = 0; |
1575 i = sizeof(ngx_resolver_hdr_t); | 1704 i = sizeof(ngx_resolver_hdr_t); |
1576 | 1705 |
1577 for (mask = 0; mask < 32; mask += 8) { | 1706 for (mask = 0; mask < 32; mask += 8) { |
1578 len = buf[i++]; | 1707 len = buf[i++]; |
1584 | 1713 |
1585 addr += octet << mask; | 1714 addr += octet << mask; |
1586 i += len; | 1715 i += len; |
1587 } | 1716 } |
1588 | 1717 |
1589 if (ngx_strcmp(&buf[i], "\7in-addr\4arpa") != 0) { | 1718 if (ngx_strcmp(&buf[i], "\7in-addr\4arpa") == 0) { |
1590 goto invalid_in_addr_arpa; | 1719 i += sizeof("\7in-addr\4arpa"); |
1591 } | 1720 |
1592 | 1721 /* lock addr mutex */ |
1593 /* lock addr mutex */ | 1722 |
1594 | 1723 rn = ngx_resolver_lookup_addr(r, addr); |
1595 rn = ngx_resolver_lookup_addr(r, addr); | 1724 |
1725 tree = &r->addr_rbtree; | |
1726 expire_queue = &r->addr_expire_queue; | |
1727 | |
1728 addr = htonl(addr); | |
1729 name.len = ngx_inet_ntop(AF_INET, &addr, text, NGX_SOCKADDR_STRLEN); | |
1730 name.data = text; | |
1731 | |
1732 goto valid; | |
1733 } | |
1734 | |
1735 invalid_in_addr_arpa: | |
1736 | |
1737 #if (NGX_HAVE_INET6) | |
1738 | |
1739 i = sizeof(ngx_resolver_hdr_t); | |
1740 | |
1741 for (octet = 15; octet >= 0; octet--) { | |
1742 if (buf[i++] != '\1') { | |
1743 goto invalid_ip6_arpa; | |
1744 } | |
1745 | |
1746 digit = ngx_hextoi(&buf[i++], 1); | |
1747 if (digit == NGX_ERROR) { | |
1748 goto invalid_ip6_arpa; | |
1749 } | |
1750 | |
1751 addr6.s6_addr[octet] = (u_char) digit; | |
1752 | |
1753 if (buf[i++] != '\1') { | |
1754 goto invalid_ip6_arpa; | |
1755 } | |
1756 | |
1757 digit = ngx_hextoi(&buf[i++], 1); | |
1758 if (digit == NGX_ERROR) { | |
1759 goto invalid_ip6_arpa; | |
1760 } | |
1761 | |
1762 addr6.s6_addr[octet] += (u_char) (digit * 16); | |
1763 } | |
1764 | |
1765 if (ngx_strcmp(&buf[i], "\3ip6\4arpa") == 0) { | |
1766 i += sizeof("\3ip6\4arpa"); | |
1767 | |
1768 /* lock addr mutex */ | |
1769 | |
1770 hash = ngx_crc32_short(addr6.s6_addr, 16); | |
1771 rn = ngx_resolver_lookup_addr6(r, &addr6, hash); | |
1772 | |
1773 tree = &r->addr6_rbtree; | |
1774 expire_queue = &r->addr6_expire_queue; | |
1775 | |
1776 name.len = ngx_inet6_ntop(addr6.s6_addr, text, NGX_SOCKADDR_STRLEN); | |
1777 name.data = text; | |
1778 | |
1779 goto valid; | |
1780 } | |
1781 | |
1782 invalid_ip6_arpa: | |
1783 #endif | |
1784 | |
1785 ngx_log_error(r->log_level, r->log, 0, | |
1786 "invalid in-addr.arpa or ip6.arpa name in DNS response"); | |
1787 return; | |
1788 | |
1789 valid: | |
1596 | 1790 |
1597 if (rn == NULL || rn->query == NULL) { | 1791 if (rn == NULL || rn->query == NULL) { |
1598 ngx_log_error(r->log_level, r->log, 0, | 1792 ngx_log_error(r->log_level, r->log, 0, |
1599 "unexpected response for %ud.%ud.%ud.%ud", | 1793 "unexpected response for %V", &name); |
1600 (addr >> 24) & 0xff, (addr >> 16) & 0xff, | |
1601 (addr >> 8) & 0xff, addr & 0xff); | |
1602 goto failed; | 1794 goto failed; |
1603 } | 1795 } |
1604 | 1796 |
1605 qident = (rn->query[0] << 8) + rn->query[1]; | 1797 qident = (rn->query[0] << 8) + rn->query[1]; |
1606 | 1798 |
1607 if (ident != qident) { | 1799 if (ident != qident) { |
1608 ngx_log_error(r->log_level, r->log, 0, | 1800 ngx_log_error(r->log_level, r->log, 0, |
1609 "wrong ident %ui response for %ud.%ud.%ud.%ud, expect %ui", | 1801 "wrong ident %ui response for %V, expect %ui", |
1610 ident, (addr >> 24) & 0xff, (addr >> 16) & 0xff, | 1802 ident, &name, qident); |
1611 (addr >> 8) & 0xff, addr & 0xff, qident); | |
1612 goto failed; | 1803 goto failed; |
1613 } | 1804 } |
1614 | 1805 |
1615 if (code == 0 && nan == 0) { | 1806 if (code == 0 && nan == 0) { |
1616 code = NGX_RESOLVE_NXDOMAIN; | 1807 code = NGX_RESOLVE_NXDOMAIN; |
1620 next = rn->waiting; | 1811 next = rn->waiting; |
1621 rn->waiting = NULL; | 1812 rn->waiting = NULL; |
1622 | 1813 |
1623 ngx_queue_remove(&rn->queue); | 1814 ngx_queue_remove(&rn->queue); |
1624 | 1815 |
1625 ngx_rbtree_delete(&r->addr_rbtree, &rn->node); | 1816 ngx_rbtree_delete(tree, &rn->node); |
1626 | 1817 |
1627 ngx_resolver_free_node(r, rn); | 1818 ngx_resolver_free_node(r, rn); |
1628 | 1819 |
1629 /* unlock addr mutex */ | 1820 /* unlock addr mutex */ |
1630 | 1821 |
1637 } | 1828 } |
1638 | 1829 |
1639 return; | 1830 return; |
1640 } | 1831 } |
1641 | 1832 |
1642 i += sizeof("\7in-addr\4arpa") + sizeof(ngx_resolver_qs_t); | 1833 i += sizeof(ngx_resolver_qs_t); |
1643 | 1834 |
1644 if (i + 2 + sizeof(ngx_resolver_an_t) >= n) { | 1835 if (i + 2 + sizeof(ngx_resolver_an_t) >= n) { |
1645 goto short_response; | 1836 goto short_response; |
1646 } | 1837 } |
1647 | 1838 |
1648 /* compression pointer to "XX.XX.XX.XX.in-addr.arpa */ | 1839 /* compression pointer to *.arpa */ |
1649 | 1840 |
1650 if (buf[i] != 0xc0 || buf[i + 1] != sizeof(ngx_resolver_hdr_t)) { | 1841 if (buf[i] != 0xc0 || buf[i + 1] != sizeof(ngx_resolver_hdr_t)) { |
1651 err = "invalid in-addr.arpa name in DNS response"; | 1842 err = "invalid in-addr.arpa or ip6.arpa name in DNS response"; |
1652 goto invalid; | 1843 goto invalid; |
1653 } | 1844 } |
1654 | 1845 |
1655 an = (ngx_resolver_an_t *) &buf[i + 2]; | 1846 an = (ngx_resolver_an_t *) &buf[i + 2]; |
1656 | 1847 |
1705 ngx_queue_remove(&rn->queue); | 1896 ngx_queue_remove(&rn->queue); |
1706 | 1897 |
1707 rn->valid = ngx_time() + (r->valid ? r->valid : ttl); | 1898 rn->valid = ngx_time() + (r->valid ? r->valid : ttl); |
1708 rn->expire = ngx_time() + r->expire; | 1899 rn->expire = ngx_time() + r->expire; |
1709 | 1900 |
1710 ngx_queue_insert_head(&r->addr_expire_queue, &rn->queue); | 1901 ngx_queue_insert_head(expire_queue, &rn->queue); |
1711 | 1902 |
1712 next = rn->waiting; | 1903 next = rn->waiting; |
1713 rn->waiting = NULL; | 1904 rn->waiting = NULL; |
1714 | 1905 |
1715 /* unlock addr mutex */ | 1906 /* unlock addr mutex */ |
1725 | 1916 |
1726 ngx_resolver_free(r, name.data); | 1917 ngx_resolver_free(r, name.data); |
1727 | 1918 |
1728 return; | 1919 return; |
1729 | 1920 |
1730 invalid_in_addr_arpa: | |
1731 | |
1732 ngx_log_error(r->log_level, r->log, 0, | |
1733 "invalid in-addr.arpa name in DNS response"); | |
1734 return; | |
1735 | |
1736 short_response: | 1921 short_response: |
1737 | 1922 |
1738 err = "short DNS response"; | 1923 err = "short DNS response"; |
1739 | 1924 |
1740 invalid: | 1925 invalid: |
1821 | 2006 |
1822 /* not found */ | 2007 /* not found */ |
1823 | 2008 |
1824 return NULL; | 2009 return NULL; |
1825 } | 2010 } |
2011 | |
2012 | |
2013 #if (NGX_HAVE_INET6) | |
2014 | |
2015 static ngx_resolver_node_t * | |
2016 ngx_resolver_lookup_addr6(ngx_resolver_t *r, struct in6_addr *addr, | |
2017 uint32_t hash) | |
2018 { | |
2019 ngx_int_t rc; | |
2020 ngx_rbtree_node_t *node, *sentinel; | |
2021 ngx_resolver_node_t *rn; | |
2022 | |
2023 node = r->addr6_rbtree.root; | |
2024 sentinel = r->addr6_rbtree.sentinel; | |
2025 | |
2026 while (node != sentinel) { | |
2027 | |
2028 if (hash < node->key) { | |
2029 node = node->left; | |
2030 continue; | |
2031 } | |
2032 | |
2033 if (hash > node->key) { | |
2034 node = node->right; | |
2035 continue; | |
2036 } | |
2037 | |
2038 /* hash == node->key */ | |
2039 | |
2040 rn = (ngx_resolver_node_t *) node; | |
2041 | |
2042 rc = ngx_memcmp(addr, &rn->addr6, 16); | |
2043 | |
2044 if (rc == 0) { | |
2045 return rn; | |
2046 } | |
2047 | |
2048 node = (rc < 0) ? node->left : node->right; | |
2049 } | |
2050 | |
2051 /* not found */ | |
2052 | |
2053 return NULL; | |
2054 } | |
2055 | |
2056 #endif | |
1826 | 2057 |
1827 | 2058 |
1828 static void | 2059 static void |
1829 ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp, | 2060 ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp, |
1830 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) | 2061 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) |
1864 node->right = sentinel; | 2095 node->right = sentinel; |
1865 ngx_rbt_red(node); | 2096 ngx_rbt_red(node); |
1866 } | 2097 } |
1867 | 2098 |
1868 | 2099 |
2100 #if (NGX_HAVE_INET6) | |
2101 | |
2102 static void | |
2103 ngx_resolver_rbtree_insert_addr6_value(ngx_rbtree_node_t *temp, | |
2104 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) | |
2105 { | |
2106 ngx_rbtree_node_t **p; | |
2107 ngx_resolver_node_t *rn, *rn_temp; | |
2108 | |
2109 for ( ;; ) { | |
2110 | |
2111 if (node->key < temp->key) { | |
2112 | |
2113 p = &temp->left; | |
2114 | |
2115 } else if (node->key > temp->key) { | |
2116 | |
2117 p = &temp->right; | |
2118 | |
2119 } else { /* node->key == temp->key */ | |
2120 | |
2121 rn = (ngx_resolver_node_t *) node; | |
2122 rn_temp = (ngx_resolver_node_t *) temp; | |
2123 | |
2124 p = (ngx_memcmp(&rn->addr6, &rn_temp->addr6, 16) | |
2125 < 0) ? &temp->left : &temp->right; | |
2126 } | |
2127 | |
2128 if (*p == sentinel) { | |
2129 break; | |
2130 } | |
2131 | |
2132 temp = *p; | |
2133 } | |
2134 | |
2135 *p = node; | |
2136 node->parent = temp; | |
2137 node->left = sentinel; | |
2138 node->right = sentinel; | |
2139 ngx_rbt_red(node); | |
2140 } | |
2141 | |
2142 #endif | |
2143 | |
2144 | |
1869 static ngx_int_t | 2145 static ngx_int_t |
1870 ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx) | 2146 ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx) |
1871 { | 2147 { |
1872 u_char *p, *s; | 2148 u_char *p, *s; |
1873 size_t len, nlen; | 2149 size_t len, nlen; |
1951 | 2227 |
1952 return NGX_OK; | 2228 return NGX_OK; |
1953 } | 2229 } |
1954 | 2230 |
1955 | 2231 |
1956 /* AF_INET only */ | |
1957 | |
1958 static ngx_int_t | 2232 static ngx_int_t |
1959 ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx) | 2233 ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx) |
1960 { | 2234 { |
1961 u_char *p, *d; | 2235 u_char *p, *d; |
1962 size_t len; | 2236 size_t len; |
1963 in_addr_t addr; | 2237 in_addr_t addr; |
1964 ngx_int_t n; | 2238 ngx_int_t n; |
1965 ngx_uint_t ident; | 2239 ngx_uint_t ident; |
1966 ngx_resolver_hdr_t *query; | 2240 ngx_resolver_hdr_t *query; |
1967 struct sockaddr_in *sin; | 2241 struct sockaddr_in *sin; |
1968 | 2242 #if (NGX_HAVE_INET6) |
1969 if (ctx->addr.sockaddr->sa_family != AF_INET) { | 2243 struct sockaddr_in6 *sin6; |
1970 return NGX_ERROR; | 2244 #endif |
1971 } | 2245 |
1972 | 2246 switch (ctx->addr.sockaddr->sa_family) { |
1973 len = sizeof(ngx_resolver_hdr_t) | 2247 |
1974 + sizeof(".255.255.255.255.in-addr.arpa.") - 1 | 2248 #if (NGX_HAVE_INET6) |
1975 + sizeof(ngx_resolver_qs_t); | 2249 case AF_INET6: |
2250 len = sizeof(ngx_resolver_hdr_t) | |
2251 + 64 + sizeof(".ip6.arpa.") - 1 | |
2252 + sizeof(ngx_resolver_qs_t); | |
2253 | |
2254 break; | |
2255 #endif | |
2256 | |
2257 default: /* AF_INET */ | |
2258 len = sizeof(ngx_resolver_hdr_t) | |
2259 + sizeof(".255.255.255.255.in-addr.arpa.") - 1 | |
2260 + sizeof(ngx_resolver_qs_t); | |
2261 } | |
1976 | 2262 |
1977 p = ngx_resolver_alloc(ctx->resolver, len); | 2263 p = ngx_resolver_alloc(ctx->resolver, len); |
1978 if (p == NULL) { | 2264 if (p == NULL) { |
1979 return NGX_ERROR; | 2265 return NGX_ERROR; |
1980 } | 2266 } |
1996 query->nns_hi = 0; query->nns_lo = 0; | 2282 query->nns_hi = 0; query->nns_lo = 0; |
1997 query->nar_hi = 0; query->nar_lo = 0; | 2283 query->nar_hi = 0; query->nar_lo = 0; |
1998 | 2284 |
1999 p += sizeof(ngx_resolver_hdr_t); | 2285 p += sizeof(ngx_resolver_hdr_t); |
2000 | 2286 |
2001 sin = (struct sockaddr_in *) ctx->addr.sockaddr; | 2287 switch (ctx->addr.sockaddr->sa_family) { |
2002 addr = ntohl(sin->sin_addr.s_addr); | 2288 |
2003 | 2289 #if (NGX_HAVE_INET6) |
2004 for (n = 0; n < 32; n += 8) { | 2290 case AF_INET6: |
2005 d = ngx_sprintf(&p[1], "%ud", (addr >> n) & 0xff); | 2291 sin6 = (struct sockaddr_in6 *) ctx->addr.sockaddr; |
2006 *p = (u_char) (d - &p[1]); | 2292 |
2007 p = d; | 2293 for (n = 15; n >= 0; n--) { |
2294 p = ngx_sprintf(p, "\1%xd\1%xd", | |
2295 sin6->sin6_addr.s6_addr[n] & 0xf, | |
2296 (sin6->sin6_addr.s6_addr[n] >> 4) & 0xf); | |
2297 } | |
2298 | |
2299 p = ngx_cpymem(p, "\3ip6\4arpa\0", 10); | |
2300 | |
2301 break; | |
2302 #endif | |
2303 | |
2304 default: /* AF_INET */ | |
2305 | |
2306 sin = (struct sockaddr_in *) ctx->addr.sockaddr; | |
2307 addr = ntohl(sin->sin_addr.s_addr); | |
2308 | |
2309 for (n = 0; n < 32; n += 8) { | |
2310 d = ngx_sprintf(&p[1], "%ud", (addr >> n) & 0xff); | |
2311 *p = (u_char) (d - &p[1]); | |
2312 p = d; | |
2313 } | |
2314 | |
2315 p = ngx_cpymem(p, "\7in-addr\4arpa\0", 14); | |
2008 } | 2316 } |
2009 | 2317 |
2010 /* query type "PTR", IN query class */ | 2318 /* query type "PTR", IN query class */ |
2011 ngx_memcpy(p, "\7in-addr\4arpa\0\0\14\0\1", 18); | 2319 p = ngx_cpymem(p, "\0\14\0\1", 4); |
2012 | 2320 |
2013 rn->qlen = (u_short) | 2321 rn->qlen = (u_short) (p - rn->query); |
2014 (p + sizeof("\7in-addr\4arpa") + sizeof(ngx_resolver_qs_t) | |
2015 - rn->query); | |
2016 | 2322 |
2017 return NGX_OK; | 2323 return NGX_OK; |
2018 } | 2324 } |
2019 | 2325 |
2020 | 2326 |