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