1. 程式人生 > >Android 乙太網轉 WiFi 熱點 (並在同一網段 192.168.0.xx)

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 default  gw 192.168.0.1 dev eth1 ,路由對了。可以ping 通
 路由對了,ping 171.90.249.254 ( ping IP 可以,但是域名不行)。網上找資料用android 的  ndc resolver setnetdns ppp0  8.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

 跟程式碼發現 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 此功能的 命令 如何嵌入到系統以及撤銷這個功能怎麼做。