DNS 解析器(DNS Resolver)
DNS 解析器模块可保护用户免受 DNS 拦截和配置更新攻击,并改进了 DNS 解析的网络性能。此模块包含用于实现 DNS 桩解析器的代码,该解析器可将 www.google.com 等名称转换为 IP 地址(例如 2001:db8::1)。DNS 桩解析器支持 Java API 元素(如 InetAddress#getAllByName 和 Network#getAllByName)以及原生网络功能,且可发送和接收 DNS 查询以及缓存结果。
Android 10 中的变化
在搭载 Android 9 及更低版本的设备上,DNS 解析器代码分布在 Bionic 和 netd 上。DNS 查找操作集中在 netd 守护程序中,以便进行系统级缓存,而应用在 Bionic 中调用函数(例如 getaddrinfo)。查询会通过 UNIX 套接字发送到 /dev/socket/dnsproxyd,再到 netd 守护程序,该守护程序会解析请求并再次调用 getaddrinfo,以发出 DNS 查找请求,然后它会缓存结果以供其他应用使用。DNS 解析器实现主要包含在 bionic/libc/dns/ 中,部分包含在 system/netd/server/dns 中。
Android 10 将 DNS 解析器代码移至 system/netd/resolv,,将其转换为 C++,然后对代码进行了翻新和重构。由于应用兼容性方面的原因,Bionic 中的代码继续存在,但系统不会再调用它们。以下源文件路径受到重构的影响:
bionic/libc/dnssystem/netd/clientsystem/netd/server/dnssystem/netd/server/DnsProxyListener.*system/netd/resolv
(1)获取ip地址(域名–>IP地址)
ConnectivityService.updateDnses() ->
DnsManager.setDnsConfigurationForNetwork() ->
mDnsResolver.setResolverConfiguration() -> IDnsResolver.aidl ()
DnsResolverService.setResolverConfiguration() ->
ResolverController.setResolverConfiguration() ->
res_cache.int resolv_set_nameservers_for_net() ->
getaddrinfo.getaddrinfo_numeric() -> getaddrinfo.android_getaddrinfofornetcontext(hostname, servname, &hints, &netcontext, result);
(2)DNS server list 设置(set name servers for a network)
_resolv_set_nameservers_for_net
http://androidxref.com/9.0.0_r3/xref/libcore/ojluni/src/main/java/java/net/InetAddress.java#1105
-
1077 /** -
1078 * Determines the IP address of a host, given the host's name. -
1097 * @param host the specified host, or {@code null}. -
1098 * @return an IP address for the given host name. -
1104 */ -
1105 public static InetAddress getByName(String host) -
1106 throws UnknownHostException { -
1107 // Android-changed: Rewritten on the top of Libcore.os. -
1108 return impl.lookupAllHostAddr(host, NETID_UNSET)[0]; -
1109 } -
1111 /** -
1112 * Given the name of a host, returns an array of its IP addresses, -
1113 * based on the configured name service on the system. -
1139 * @param host the name of the host, or {@code null}. -
1140 * @return an array of all the IP addresses for a given host name. -
1149 */ -
1150 public static InetAddress[] getAllByName(String host) -
1151 throws UnknownHostException { -
1152 // Android-changed: Resolves a hostname using Libcore.os. -
1153 // Also, returns both the Inet4 and Inet6 loopback for null/empty host -
1154 return impl.lookupAllHostAddr(host, NETID_UNSET).clone(); -
1155 }
lookupAllHostAddr在Android M上的名字叫做getAllByNameImpl
http://androidxref.com/9.0.0_r3/xref/libcore/ojluni/src/main/java/java/net/Inet6AddressImpl.java#88
-
79 // BEGIN Android-changed: Rewrote hostname lookup methods on top of Libcore.os. -
80 /* -
81 public native String getLocalHostName() throws UnknownHostException; -
82 public native InetAddress[] -
83 lookupAllHostAddr(String hostname) throws UnknownHostException; -
84 public native String getHostByAddr(byte[] addr) throws UnknownHostException; -
85 private native boolean isReachable0(byte[] addr, int scope, int timeout, byte[] inf, int ttl, int if_scope) throws IOException; -
86 */ -
87 @Override -
88 public InetAddress[] lookupAllHostAddr(String host, int netId) throws UnknownHostException { -
89 if (host == null || host.isEmpty()) { -
90 // Android-changed: Return both the Inet4 and Inet6 loopback addresses -
91 // when host == null or empty. -
92 return loopbackAddresses(); -
93 } -
94 -
95 // Is it a numeric address? -
96 InetAddress result = InetAddress.parseNumericAddressNoThrow(host); -
97 if (result != null) { -
98 result = InetAddress.disallowDeprecatedFormats(host, result); -
99 if (result == null) { -
100 throw new UnknownHostException("Deprecated IPv4 address format: " + host); -
101 } -
102 return new InetAddress[] { result }; -
103 } -
104 -
105 return lookupHostByName(host, netId); -
106 } -
323 // BEGIN Android-changed: Let loopbackAddresses() return both Inet4 and Inet6 loopbacks. -
324 @Override -
325 public InetAddress[] loopbackAddresses() { -
326 synchronized (Inet6AddressImpl.class) { -
327 // We avoid initializing anyLocalAddress during <clinit> to avoid issues -
328 // caused by the dependency chains of these classes. InetAddress depends on -
329 // InetAddressImpl, but Inet6Address & Inet4Address are its subclasses. -
330 // Also see {@code anyLocalAddress). -
331 if (loopbackAddresses == null) { -
332 loopbackAddresses = new InetAddress[]{Inet6Address.LOOPBACK, Inet4Address.LOOPBACK}; -
333 } -
334 -
335 return loopbackAddresses; -
336 } -
337 }
http://androidxref.com/9.0.0_r3/xref/libcore/ojluni/src/main/java/java/net/InetAddress.java#1622
-
1622 static InetAddress parseNumericAddressNoThrow(String address) { -
1623 // Accept IPv6 addresses (only) in square brackets for compatibility. -
1624 if (address.startsWith("[") && address.endsWith("]") && address.indexOf(':') != -1) { -
1625 address = address.substring(1, address.length() - 1); -
1626 } -
1627 StructAddrinfo hints = new StructAddrinfo(); -
1628 hints.ai_flags = AI_NUMERICHOST; -
1629 InetAddress[] addresses = null; -
1630 try { -
1631 addresses = Libcore.os.android_getaddrinfo(address, hints, NETID_UNSET); -
1632 } catch (GaiException ignored) { -
1633 } -
1634 return (addresses != null) ? addresses[0] : null; -
1635 }
http://androidxref.com/9.0.0_r3/xref/libcore/ojluni/src/main/java/java/net/Inet6AddressImpl.java#115
-
108 /** -
109 * Resolves a hostname to its IP addresses using a cache. -
110 * -
111 * @param host the hostname to resolve. -
112 * @param netId the network to perform resolution upon. -
113 * @return the IP addresses of the host. -
114 */ -
115 private static InetAddress[] lookupHostByName(String host, int netId) -
116 throws UnknownHostException { -
117 BlockGuard.getThreadPolicy().onNetwork(); -
118 // Do we have a result cached? -
119 Object cachedResult = addressCache.get(host, netId); -
120 if (cachedResult != null) { -
121 if (cachedResult instanceof InetAddress[]) { -
122 // A cached positive result. -
123 return (InetAddress[]) cachedResult; -
124 } else { -
125 // A cached negative result. -
126 throw new UnknownHostException((String) cachedResult); -
127 } -
128 } -
129 try { -
130 StructAddrinfo hints = new StructAddrinfo(); -
131 hints.ai_flags = AI_ADDRCONFIG; -
132 hints.ai_family = AF_UNSPEC; -
133 // If we don't specify a socket type, every address will appear twice, once -
134 // for SOCK_STREAM and one for SOCK_DGRAM. Since we do not return the family -
135 // anyway, just pick one. -
136 hints.ai_socktype = SOCK_STREAM; -
137 InetAddress[] addresses = Libcore.os.android_getaddrinfo(host, hints, netId); -
138 // TODO: should getaddrinfo set the hostname of the InetAddresses it returns? -
139 for (InetAddress address : addresses) { -
140 address.holder().hostName = host; -
141 address.holder().originalHostName = host; -
142 } -
143 addressCache.put(host, netId, addresses); -
144 return addresses; -
145 } catch (GaiException gaiException) { -
146 // If the failure appears to have been a lack of INTERNET permission, throw a clear -
147 // SecurityException to aid in debugging this common mistake. -
148 // http://code.google.com/p/android/issues/detail?id=15722 -
149 if (gaiException.getCause() instanceof ErrnoException) { -
150 if (((ErrnoException) gaiException.getCause()).errno == EACCES) { -
151 throw new SecurityException("Permission denied (missing INTERNET permission?)", gaiException); -
152 } -
153 } -
154 // Otherwise, throw an UnknownHostException. -
155 String detailMessage = "Unable to resolve host \"" + host + "\": " + Libcore.os.gai_strerror(gaiException.error); -
156 addressCache.putUnknownHost(host, netId, detailMessage); -
157 throw gaiException.rethrowAsUnknownHostException(detailMessage); -
158 } -
159 }
上面都调用了Libcore.os.android_getaddrinfo
http://androidxref.com/9.0.0_r3/xref/libcore/luni/src/main/java/libcore/io/Libcore.java#19
-
19public final class Libcore { -
20 private Libcore() { } -
21 -
22 /** -
23 * Direct access to syscalls. Code should strongly prefer using {@link #os} -
24 * unless it has a strong reason to bypass the helpful checks/guards that it -
25 * provides. -
26 */ -
27 public static Os rawOs = new Linux(); -
28 -
29 /** -
30 * Access to syscalls with helpful checks/guards. -
31 */ -
32 public static Os os = new BlockGuardOs(rawOs); -
33}
Os对象是一系列系统调用的抽象接口,从LibCore.java中可以看出它是通过Linux这个类实现的
http://androidxref.com/9.0.0_r3/xref/libcore/luni/src/main/java/libcore/io/Linux.java#53
-
48public final class Linux implements Os { -
49 Linux() { } -
53 public native InetAddress[] android_getaddrinfo(String node, StructAddrinfo hints, int netId) throws GaiException;
http://androidxref.com/9.0.0_r3/xref/libcore/luni/src/main/java/libcore/io/BlockGuardOs.java#164
-
40/** -
41 * Informs BlockGuard of any activity it should be aware of. -
42 */ -
43public class BlockGuardOs extends ForwardingOs { -
44 public BlockGuardOs(Os os) { -
45 super(os); -
46 } -
164 @Override public InetAddress[] android_getaddrinfo(String node, StructAddrinfo hints, int netId) throws GaiException { -
165 // With AI_NUMERICHOST flag set, the node must a numerical network address, therefore no -
166 // host address lookups will be performed. In this case, it is fine to perform on main -
167 // thread. -
168 boolean isNumericHost = (hints.ai_flags & AI_NUMERICHOST) != 0; -
169 if (!isNumericHost) { -
170 BlockGuard.getThreadPolicy().onNetwork(); -
171 } -
172 return os.android_getaddrinfo(node, hints, netId); -
173 }
再找OS类
http://androidxref.com/9.0.0_r3/xref/libcore/luni/src/main/java/libcore/io/Os.java#50
-
47public interface Os { -
50 public InetAddress[] android_getaddrinfo(String node, StructAddrinfo hints, int netId) throws GaiException;
参考
得知Linux.java通过JNI (libcore_io_Linux.cpp)调用linux的posix API,那么知道了,C层的实现都在libcore_io_Linux.cpp中,咱们来看下。
http://androidxref.com/9.0.0_r3/xref/libcore/luni/src/main/native/libcore_io_Linux.cpp#1244
-
1244static jobjectArray Linux_android_getaddrinfo(JNIEnv* env, jobject, jstring javaNode, -
1245 jobject javaHints, jint netId) { -
1246 ScopedUtfChars node(env, javaNode); -
1247 if (node.c_str() == NULL) { -
1248 return NULL; -
1249 } -
1250 -
1251 static jfieldID flagsFid = env->GetFieldID(JniConstants::structAddrinfoClass, "ai_flags", "I"); -
1252 static jfieldID familyFid = env->GetFieldID(JniConstants::structAddrinfoClass, "ai_family", "I"); -
1253 static jfieldID socktypeFid = env->GetFieldID(JniConstants::structAddrinfoClass, "ai_socktype", "I"); -
1254 static jfieldID protocolFid = env->GetFieldID(JniConstants::structAddrinfoClass, "ai_protocol", "I"); -
1255 -
1256 addrinfo hints; -
1257 memset(&hints, 0, sizeof(hints)); -
1258 hints.ai_flags = env->GetIntField(javaHints, flagsFid); -
1259 hints.ai_family = env->GetIntField(javaHints, familyFid); -
1260 hints.ai_socktype = env->GetIntField(javaHints, socktypeFid); -
1261 hints.ai_protocol = env->GetIntField(javaHints, protocolFid); -
1262 -
1263 addrinfo* addressList = NULL; -
1264 errno = 0; -
1265 int rc = android_getaddrinfofornet(node.c_str(), NULL, &hints, netId, 0, &addressList); -
1266 std::unique_ptr<addrinfo, addrinfo_deleter> addressListDeleter(addressList); -
1267 if (rc != 0) { -
1268 throwGaiException(env, "android_getaddrinfo", rc); -
1269 return NULL; -
1270 } -
1271 -
1272 // Count results so we know how to size the output array. -
1273 int addressCount = 0; -
1274 for (addrinfo* ai = addressList; ai != NULL; ai = ai->ai_next) { -
1275 if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) { -
1276 ++addressCount; -
1277 } else { -
1278 ALOGE("android_getaddrinfo unexpected ai_family %i", ai->ai_family); -
1279 } -
1280 } -
1281 if (addressCount == 0) { -
1282 return NULL; -
1283 } -
1284 -
1285 // Prepare output array. -
1286 jobjectArray result = env->NewObjectArray(addressCount, JniConstants::inetAddressClass, NULL); -
1287 if (result == NULL) { -
1288 return NULL; -
1289 } -
1290 -
1291 // Examine returned addresses one by one, save them in the output array. -
1292 int index = 0; -
1293 for (addrinfo* ai = addressList; ai != NULL; ai = ai->ai_next) { -
1294 if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) { -
1295 // Unknown address family. Skip this address. -
1296 ALOGE("android_getaddrinfo unexpected ai_family %i", ai->ai_family); -
1297 continue; -
1298 } -
1299 -
1300 // Convert each IP address into a Java byte array. -
1301 sockaddr_storage& address = *reinterpret_cast<sockaddr_storage*>(ai->ai_addr); -
1302 ScopedLocalRef<jobject> inetAddress(env, sockaddrToInetAddress(env, address, NULL)); -
1303 if (inetAddress.get() == NULL) { -
1304 return NULL; -
1305 } -
1306 env->SetObjectArrayElement(result, index, inetAddress.get()); -
1307 ++index; -
1308 } -
1309 return result; -
1310}
调用android_getaddrinfofornet()
http://androidxref.com/9.0.0_r3/xref/libcore/luni/src/main/native/Portability.h#28
-
28static inline int android_getaddrinfofornet(const char* hostname, const char* servname, -
29 const struct addrinfo* hints, unsigned /*netid*/, unsigned /*mark*/, struct addrinfo** res) { -
30 return getaddrinfo(hostname, servname, hints, res); -
31}
最终调用到bionic/libc/dns/net/getaddrinfo.c
http://androidxref.com/9.0.0_r3/xref/bionic/libc/dns/net/getaddrinfo.c#564
-
562__BIONIC_WEAK_FOR_NATIVE_BRIDGE -
563int -
564getaddrinfo(const char *hostname, const char *servname, -
565 const struct addrinfo *hints, struct addrinfo **res) -
566{ -
567 return android_getaddrinfofornet(hostname, servname, hints, NETID_UNSET, MARK_UNSET, res); -
568} -
570__BIONIC_WEAK_FOR_NATIVE_BRIDGE -
571int -
572android_getaddrinfofornet(const char *hostname, const char *servname, -
573 const struct addrinfo *hints, unsigned netid, unsigned mark, struct addrinfo **res) -
574{ -
575 struct android_net_context netcontext = { -
576 .app_netid = netid, -
577 .app_mark = mark, -
578 .dns_netid = netid, -
579 .dns_mark = mark, -
580 .uid = NET_CONTEXT_INVALID_UID, -
581 }; -
582 return android_getaddrinfofornetcontext(hostname, servname, hints, &netcontext, res); -
583} -
584 -
585__BIONIC_WEAK_FOR_NATIVE_BRIDGE -
586int -
587android_getaddrinfofornetcontext(const char *hostname, const char *servname, -
588 const struct addrinfo *hints, const struct android_net_context *netcontext, -
589 struct addrinfo **res) -
590{ -
591 struct addrinfo sentinel; -
592 struct addrinfo *cur; -
593 int error = 0; -
594 struct addrinfo ai; -
595 struct addrinfo ai0; -
596 struct addrinfo *pai; -
597 const struct explore *ex; -
598 -
599 /* hostname is allowed to be NULL */ -
600 /* servname is allowed to be NULL */ -
601 /* hints is allowed to be NULL */ -
602 assert(res != NULL); -
603 assert(netcontext != NULL); -
604 memset(&sentinel, 0, sizeof(sentinel)); -
605 cur = &sentinel; -
606 pai = &ai; -
607 pai->ai_flags = 0; -
608 pai->ai_family = PF_UNSPEC; -
609 pai->ai_socktype = ANY; -
610 pai->ai_protocol = ANY; -
611 pai->ai_addrlen = 0; -
612 pai->ai_canonname = NULL; -
613 pai->ai_addr = NULL; -
614 pai->ai_next = NULL; -
615 -
616 if (hostname == NULL && servname == NULL) -
617 return EAI_NONAME; -
618 if (hints) { -
619 /* error check for hints */ -
620 if (hints->ai_addrlen || hints->ai_canonname || -
621 hints->ai_addr || hints->ai_next) -
622 ERR(EAI_BADHINTS); /* xxx */ -
623 if (hints->ai_flags & ~AI_MASK) -
624 ERR(EAI_BADFLAGS); -
625 switch (hints->ai_family) { -
626 case PF_UNSPEC: -
627 case PF_INET: -
628#ifdef INET6 -
629 case PF_INET6: -
630#endif -
631 break; -
632 default: -
633 ERR(EAI_FAMILY); -
634 } -
635 memcpy(pai, hints, sizeof(*pai)); -
636 -
637 /* -
638 * if both socktype/protocol are specified, check if they -
639 * are meaningful combination. -
640 */ -
641 if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) { -
642 for (ex = explore; ex->e_af >= 0; ex++) { -
643 if (pai->ai_family != ex->e_af) -
644 continue; -
645 if (ex->e_socktype == ANY) -
646 continue; -
647 if (ex->e_protocol == ANY) -
648 continue; -
649 if (pai->ai_socktype == ex->e_socktype -
650 && pai->ai_protocol != ex->e_protocol) { -
651 ERR(EAI_BADHINTS); -
652 } -
653 } -
654 } -
655 } -
656 -
657 /* -
658 * check for special cases. (1) numeric servname is disallowed if -
659 * socktype/protocol are left unspecified. (2) servname is disallowed -
660 * for raw and other inet{,6} sockets. -
661 */ -
662 if (MATCH_FAMILY(pai->ai_family, PF_INET, 1) -
663#ifdef PF_INET6 -
664 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1) -
665#endif -
666 ) { -
667 ai0 = *pai; /* backup *pai */ -
668 -
669 if (pai->ai_family == PF_UNSPEC) { -
670#ifdef PF_INET6 -
671 pai->ai_family = PF_INET6; -
672#else -
673 pai->ai_family = PF_INET; -
674#endif -
675 } -
676 error = get_portmatch(pai, servname); -
677 if (error) -
678 ERR(error); -
679 -
680 *pai = ai0; -
681 } -
682 -
683 ai0 = *pai; -
684 -
685 /* NULL hostname, or numeric hostname */ -
686 for (ex = explore; ex->e_af >= 0; ex++) { -
687 *pai = ai0; -
688 -
689 /* PF_UNSPEC entries are prepared for DNS queries only */ -
690 if (ex->e_af == PF_UNSPEC) -
691 continue; -
692 -
693 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) -
694 continue; -
695 if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) -
696 continue; -
697 if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) -
698 continue; -
699 -
700 if (pai->ai_family == PF_UNSPEC) -
701 pai->ai_family = ex->e_af; -
702 if (pai->ai_socktype == ANY && ex->e_socktype != ANY) -
703 pai->ai_socktype = ex->e_socktype; -
704 if (pai->ai_protocol == ANY && ex->e_protocol != ANY) -
705 pai->ai_protocol = ex->e_protocol; -
706 -
707 if (hostname == NULL) -
708 error = explore_null(pai, servname, &cur->ai_next); -
709 else -
710 error = explore_numeric_scope(pai, hostname, servname, -
711 &cur->ai_next); -
712 -
713 if (error) -
714 goto free; -
715 -
716 while (cur->ai_next) -
717 cur = cur->ai_next; -
718 } -
719 -
720 /* -
721 * XXX -
722 * If numeric representation of AF1 can be interpreted as FQDN -
723 * representation of AF2, we need to think again about the code below. -
724 */ -
725 if (sentinel.ai_next) -
726 goto good; -
727 -
728 if (hostname == NULL) -
729 ERR(EAI_NODATA); -
730 if (pai->ai_flags & AI_NUMERICHOST) -
731 ERR(EAI_NONAME); -
732 -
733#if defined(__ANDROID__) -
734 int gai_error = android_getaddrinfo_proxy( -
735 hostname, servname, hints, res, netcontext->app_netid); -
736 if (gai_error != EAI_SYSTEM) { -
737 return gai_error; -
738 } -
739#endif -
740 -
741 /* -
742 * hostname as alphabetical name. -
743 * we would like to prefer AF_INET6 than AF_INET, so we'll make a -
744 * outer loop by AFs. -
745 */ -
746 for (ex = explore; ex->e_af >= 0; ex++) { -
747 *pai = ai0; -
748 -
749 /* require exact match for family field */ -
750 if (pai->ai_family != ex->e_af) -
751 continue; -
752 -
753 if (!MATCH(pai->ai_socktype, ex->e_socktype, -
754 WILD_SOCKTYPE(ex))) { -
755 continue; -
756 } -
757 if (!MATCH(pai->ai_protocol, ex->e_protocol, -
758 WILD_PROTOCOL(ex))) { -
759 continue; -
760 } -
761 -
762 if (pai->ai_socktype == ANY && ex->e_socktype != ANY) -
763 pai->ai_socktype = ex->e_socktype; -
764 if (pai->ai_protocol == ANY && ex->e_protocol != ANY) -
765 pai->ai_protocol = ex->e_protocol; -
766 -
767 error = explore_fqdn( -
768 pai, hostname, servname, &cur->ai_next, netcontext); -
769 -
770 while (cur && cur->ai_next) -
771 cur = cur->ai_next; -
772 } -
773 -
774 /* XXX */ -
775 if (sentinel.ai_next) -
776 error = 0; -
777 -
778 if (error) -
779 goto free; -
780 if (error == 0) { -
781 if (sentinel.ai_next) { -
782 good: -
783 *res = sentinel.ai_next; -
784 return SUCCESS; -
785 } else -
786 error = EAI_FAIL; -
787 } -
788 free: -
789 bad: -
790 if (sentinel.ai_next) -
791 freeaddrinfo(sentinel.ai_next); -
792 *res = NULL; -
793 return error; -
794}
DNS解析流程
2169

被折叠的 条评论
为什么被折叠?



