根据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) << __func__ << " ttgctt force 34 for ipv6";

+ return 34;

}

} else {

return 1;

@@ -1406,16 +1407,17 @@

query_ipv6 = have_ipv6(netcontext->app_mark, netcontext->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;

}

参考阅读

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。