android|Android 以太网转 WiFi 热点 (并在同一网段 192.168.0.xx)

命令如下:
首先打开盒子的 wifi 热点功能,再用以下命令
ip link set eth0 up;
ip link add eth1 type bridge ; ip link set eth0 master eth1;
busybox ifconfig eth0 0.0.0.0
ip link set wlan0 master eth1
busybox ifconfig wlan0 0.0.0.0
ip link set eth1 down; ip link set eth1 up;
/system/bin/iptables -F
/system/bin/iptables -X
/system/bin/iptables -t nat -F
同时,系统层要改两个地方
1 frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetNetworkFactory.java
// If we don't already have an interface, and if this interface matches
// our regex, start tracking it.
-if (!iface.matches(mIfaceMatch) || isTrackingInterface())
+Log.d(TAG, "edit by Wade Started tracking interface " + iface + " " + isTrackingInterface());
+if (!iface.matches("eth1") || isTrackingInterface())
2 device/rockchip/common/init.rockchip.rc
加一个 service
service dhcpcd_eth1 /system/bin/dhcpcd -aABDKL
class late_start
disabled
oneshot


分析和说明。
1.命令分析:
发现路由不对( ping -I eth1 网关 okay, ping 网关 no okay),就加了一条,busybox route add defaultgw 192.168.0.1 dev eth1 ,路由对了。可以ping 通
路由对了,ping 171.90.249.254 ( ping IP 可以,但是域名不行)。网上找资料用android 的ndc resolver setnetdns ppp08.8.8.8 8.8.4.4 解决问题。
自此,盒子 ping 外网可以了。

ping 没有问题,但是在 机子上用浏览器却上不了网,

随便找了一个 app ,加了一个测试代码来测试是否有 dns 或者 interface:

public void onClick(View v) {
System.out.println("test by Wade get dns test !");
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
for(Network network :connectivityManager.getAllNetworks())
{
NetworkInfo networkInfo = connectivityManager.getNetworkInfo(network);
if (networkInfo.isConnected()) {
LinkProperties linkProperties = connectivityManager.getLinkProperties(network);
linkProperties.getDnsServers().toString();
System.out.println("test by Wade get dns test !" + linkProperties.getDnsServers().toString());
System.out.println("test by Wade get interface test !" + linkProperties.getInterfaceName().toString());
System.out.println("test by Wade get interface test !" + linkProperties.getAllInterfaceNames().toString());
}
}
}

发现在 eth1 (网桥,我把 br0 改成了 eth1)的时候.. interface 为空,也就是 android 认为没有联网。

改为 eth1 的原因是猜测 android 会根据命令来处理网络连接。

后在网上偶然看到 ./frameworks/base/core/res/res/values/config.xml 里的 config_ethernet_iface_regex 是以太网的匹配,于是往下查

在 frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetNetworkFactory.java 里 mIfaceMatch 的 matches,导致只能增加 eth0 这个接口,随做
了相应的改动。

在修改后发现

01-01 12:02:34.701 462-1996/system_process D/NetUtils: dhcp_do_request failed : eth1 (new)
01-01 12:02:34.701 462-1996/system_process E/EthernetNetworkFactory: DHCP request error:Timed out waiting for dhcpcd to start
【android|Android 以太网转 WiFi 热点 (并在同一网段 192.168.0.xx)】 跟代码发现 dhcpcd_eth1 这个服务没有,在 init.rc 里加上后就可以了。

到这个时候,浏览器可以上网了,但是上网的网卡是我们虚拟出来的网桥eth1, linkProperties.getInterfaceName().toString()) 也可以看到 eth1 了。




2 确认了一些东西

比如 ifconfig 等命令的实际是改了内核的一些状态,内核再通过 kobject_event 的方式传给上层, 网络层用 netlink 等实现对内核 event 的接收,进而知道其状态

再比如 android 系统对网络ethernet 的处理,不是按命令来的,有他自己的一套:比如检测到了有新的网卡后,他自己会实现 dhcpcd , dns 等网络信息的获取。如果屏蔽了EthernetNetworkFactory.java 的一些东西。用命令配置 eth0 到能 Ping能 wget ,在浏览器中还是不能上网


3:产品化

我只是把功能实现,如果要做成产品,还有一些路要走:
1 没做热点之前,如何保证 eth0 正常功能。
2 如 eth0 ,eth1 重写一个 类似 EthernetNetworkFactory.java 的class 来处理,比如 ppp0 这样的接口
3 在实现功能后,我再手动开关 wlan0 ,会一直报错,怎么解决。
4 此功能的 命令 如何嵌入到系统以及撤销这个功能怎么做。

















    推荐阅读