Android 12(S) IPV4优先IPV6(优先使用IPv4地址)的实现
根据RFC 6724中 规定 android 会优先选择IPv6 地址而不是 IPv4 地址,当整个网络中,同时支持IPv4和IPv6 地址时,设备中的应用请求服务器DNS时,会优先返回IPv6地址。
(图片来源网络,侵删)
假如IPv6服务器支持内容不够完善,则应用显示内容会与IPv4服务器不一致,甚至有问题。
因此有需求是定制设备平台,使得 IPV4优先IPV6,主要修改2个地方:
1. 当设备或平台连接网络时,原来是先请求ipv6地址,再请求ipv4地址,这样会使用应用会先拿到ipv6地址,所以需要调整顺序,让ipv4先请求dhcp地址,再请求ipv6。
2. DNS域名解析时,调整解析DNS的优先顺序,即先解析IPv4地址,再解析IPv6地址,注:android 12在DnsResolver代码中。
接下来对这2个修改点进行逐一修改并说明。
1. 当设备或平台连接网络时,原来是先请求ipv6地址,再请求ipv4地址,这样会使用应用会先拿到ipv6地址,所以需要调整顺序,让ipv4先请求dhcp地址,再请求ipv6。
文件:packages/modules/NetworkStack/src/android/net/ip/IpClient.java
修改差异如下:
--- a/modules/NetworkStack/src/android/net/ip/IpClient.java +++ b/modules/NetworkStack/src/android/net/ip/IpClient.java @@ -161,6 +161,8 @@ private final NetworkInformationShim mShim = NetworkInformationShimImpl.newInstance(); private final IpProvisioningMetrics mIpProvisioningMetrics = new IpProvisioningMetrics(); private final NetworkQuirkMetrics mNetworkQuirkMetrics; + //CN project let get ipv4 first and then ipv6, tiangui.tang @2023.9.7 //用于区别自定义code与AOSP + private final boolean bStartIPv6AfterIPv4 = true; /** * Dump all state machine and connectivity packet logs to the specified writer. @@ -1734,7 +1736,21 @@ recordMetric(failureType); mCallback.onProvisioningFailure(mLinkProperties); } + private void enqueueJumpToStoppingState(final DisconnectCode code) { + deferMessage(obtainMessage(CMD_JUMP_RUNNING_TO_STOPPING, code.getNumber())); + } + private void startIPv6AfterIPv4() { + if (bStartIPv6AfterIPv4 == false) { + return; + } + Log.d(mTag, "startIPv6AfterIPv4"); + if (mConfiguration.mEnableIPv6 && !startIPv6()) { + doImmediateProvisioningFailure(IpManagerEvent.ERROR_STARTING_IPV6); + enqueueJumpToStoppingState(DisconnectCode.DC_ERROR_STARTING_IPV6); + return; + } + } private boolean startIPv4() { // If we have a StaticIpConfiguration attempt to apply it and // handle the result accordingly. @@ -1744,6 +1760,7 @@ } else { return false; } + startIPv6AfterIPv4(); } else { if (mDhcpClient != null) { Log.wtf(mTag, "DhcpClient should never be non-null in startIPv4()"); @@ -2229,7 +2246,7 @@ mPacketTracker = createPacketTracker(); if (mPacketTracker != null) mPacketTracker.start(mConfiguration.mDisplayName); - if (mConfiguration.mEnableIPv6 && !startIPv6()) { + if ((bStartIPv6AfterIPv4 == false) && mConfiguration.mEnableIPv6 && !startIPv6()) { doImmediateProvisioningFailure(IpManagerEvent.ERROR_STARTING_IPV6); enqueueJumpToStoppingState(DisconnectCode.DC_ERROR_STARTING_IPV6); return; @@ -2414,6 +2431,7 @@ } case EVENT_DHCPACTION_TIMEOUT: + startIPv6AfterIPv4(); stopDhcpAction(); break; @@ -2431,6 +2449,7 @@ case DhcpClient.CMD_CONFIGURE_LINKADDRESS: { final LinkAddress ipAddress = (LinkAddress) msg.obj; + startIPv6AfterIPv4(); if (mInterfaceCtrl.setIPv4Address(ipAddress)) { mDhcpClient.sendMessage(DhcpClient.EVENT_LINKADDRESS_CONFIGURED); } else {
2. DNS域名解析时,调整解析DNS的优先顺序,即先解析IPv4地址,再解析IPv6地址,注:android 12在DnsResolver代码中。
diff --git a/modules/DnsResolver/getaddrinfo.cpp b/modules/DnsResolver/getaddrinfo.cpp --- a/modules/DnsResolver/getaddrinfo.cpp +++ b/modules/DnsResolver/getaddrinfo.cpp @@ -1147,7 +1147,8 @@ return 1; } else { /* All other IPv6 addresses, including global unicast addresses. */ //DNS解析出来的地址进行排序,IPv4(return 35) 比IPv6(改为return 34)更高优先级 - return 40; + LOG(DEBUG) uid); query_ipv4 = have_ipv4(netcontext->app_mark, netcontext->uid); } //调整顺序,先请求IPv4对应的DNS,再请求IPv6 - if (query_ipv6) { - q.qtype = T_AAAA; - if (query_ipv4) { + //query_ipv6 = 0; + if (query_ipv4) { + q.qtype = T_A; + if (query_ipv6) { q.next = &q2; q2.name = name; q2.qclass = C_IN; - q2.qtype = T_A; + q2.qtype = T_AAAA; } - } else if (query_ipv4) { - q.qtype = T_A; + } else if (query_ipv6) { + q.qtype = T_AAAA; } else { return EAI_NODATA; } @@ -1452,7 +1454,7 @@ cur->ai_next = ai; while (cur && cur->ai_next) cur = cur->ai_next; } if (q.next) { ai = getanswer(q2.answer, q2.n, q2.name, q2.qtype, pai, &he); if (ai) cur->ai_next = ai; }
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。