1 方法一双网口是两块独立的网卡桥接,linux中可以实现桥接,实现将两块网卡插入同一个交换一样。
Android的kernal中不支持brctl,Android先需要集成busybox1工具。
busybox1.11 ifconfig
busybox1.11 ifconfig eth0 up
busybox1.11 ifconfig eth1 up
busybox1.11 brctl addbr br0
busybox1.11 brctl addif br0 eth0
busybox1.11 brctl addif br0 eth1
busybox1.11 ifconfig eth0 0.0.0.0
busybox1.11 ifconfig eth1 0.0.0.0
busybox1.11 ifconfig br0 192.168.1.2 netmask 255.255.255.0 #两块网口变成一块br0的网口
busybox1.11 route add default gw 192.168.1.1
ptables -A FORWARD -i eth0 -o eth1 -j ACCEPT
iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT
iptables -D FORWARD 4 /* 删除natctrl_FORWARD规则,FORWARD中的第4条规则 */
2,方法二两块网口仍然是独立的,可以独立设置IP地址,只是通过路由配置可以联通。
在ConnectivityService中更新连接状态updateLinkProperties时,把以太网的路由表写入了legacy_system路由表里面,这张路由表优先级高,会先使用。验证pass,可以ping通两个网段不同的路由器。
frameworks/base/services/core/java/com/android/server/ConnectivityService.java
private void updateLinkProperties(NetworkAgentInfo networkAgent, LinkProperties newLp,
LinkProperties oldLp) {
int netId = networkAgent.network.netId;
updateRoutes(newLp, oldLp, netId);
updateDnses(newLp, oldLp, netId);
+ log("trchen updateLinkProperties "+ networkAgent + " newLp= " + newLp);
+ saveEthernetInformation(newLp,true);
+
+ int NetworkType = networkAgent.networkInfo.getType();
+ if(NetworkType == ConnectivityManager.TYPE_ETHERNET) {
+ CompareResult<RouteInfo> routeDiff = new CompareResult<RouteInfo>();
+ for (RouteInfo route : newLp.getAllRoutes()) {
+ if (route.hasGateway()) continue;
+ if (!(route.getDestination().getAddress() instanceof Inet4Address)) continue;
+ try {
+ log("trchen addLegacyRouteForNetId " );
+ mNMS.addLegacyRouteForNetId(netId, route, getCallingUid());
+
+ } catch (Exception e) {
+ // never crash - catch them all
+ loge("Exception trying to add a route: " + e);
+ }
+ }
+ }
同时,把LinkProperties中的IP地址、网关、dns信息保存到系统属性中,供给app查询,这里非常规改法。
+ private final static String nullIpInfo = "0.0.0.0";
+ private void saveEthernetInformation(LinkProperties mLinkProperties,boolean up) {
+ Log.i(TAG, "saveEthernetInformation " + mLinkProperties.getInterfaceName());
+ Log.i(TAG, "saveEthernetInformation up " +up);
+ if(up){
+ SystemProperties.set("dhcp."+ mLinkProperties.getInterfaceName() +".ipaddress",getLinkIpAddress(mLinkProperties));
+ SystemProperties.set("dhcp."+ mLinkProperties.getInterfaceName() +".mask",getLinkNetmask(mLinkProperties));
+ SystemProperties.set("dhcp."+ mLinkProperties.getInterfaceName() +".gateway",getLinkGateway(mLinkProperties));
+ SystemProperties.set("dhcp."+ mLinkProperties.getInterfaceName() +".dns1",getLinkDns(mLinkProperties));
+ }else{
+ SystemProperties.set("dhcp."+ mLinkProperties.getInterfaceName() +".ipaddress",null);
+ SystemProperties.set("dhcp."+ mLinkProperties.getInterfaceName() +".mask",null);
+ SystemProperties.set("dhcp."+ mLinkProperties.getInterfaceName() +".gateway",null);
+ SystemProperties.set("dhcp."+ mLinkProperties.getInterfaceName() +".dns1",null);
+ }
+ Log.i(TAG, "saveEthernetInformation ipaddress " +SystemProperties.get("dhcp."+ mLinkProperties.getInterfaceName() +".ipaddress")+" ="+mLinkProperties.getInterfaceName());
+ }
+ private String getLinkIpAddress(LinkProperties mLinkProperties) {
+ for (LinkAddress l : mLinkProperties.getLinkAddresses()) {
+ InetAddress source = l.getAddress();
+ //Log.d(TAG, "getIpAddress: " + source.getHostAddress());
+ if (source instanceof Inet4Address) {
+ return source.getHostAddress();
+ }
+ }
+ return "";
+ }
+ SystemProperties.set("dhcp."+ mLinkProperties.getInterfaceName() +".ipaddress",null);
+ SystemProperties.set("dhcp."+ mLinkProperties.getInterfaceName() +".mask",null);
+ SystemProperties.set("dhcp."+ mLinkProperties.getInterfaceName() +".gateway",null);
+ SystemProperties.set("dhcp."+ mLinkProperties.getInterfaceName() +".dns1",null);
+ }
+ Log.i(TAG, "saveEthernetInformation ipaddress " +SystemProperties.get("dhcp."+ mLinkProperties.getInterfaceName() +".ipaddress")+" ="+mLinkProperties.getInterfaceName());
+ }
+ private String getLinkIpAddress(LinkProperties mLinkProperties) {
+ for (LinkAddress l : mLinkProperties.getLinkAddresses()) {
+ InetAddress source = l.getAddress();
+ //Log.d(TAG, "getIpAddress: " + source.getHostAddress());
+ if (source instanceof Inet4Address) {
+ return source.getHostAddress();
+ }
+ }
+ return "";
+ }
+ private String getLinkNetmask(LinkProperties mLinkProperties) {
+ for (LinkAddress l : mLinkProperties.getLinkAddresses()) {
+ InetAddress source = l.getAddress();
+ if (source instanceof Inet4Address) {
+ return linkprefix2netmask(l.getPrefixLength());
+ }
+ }
+ return "";
+ }
+ private String linkprefix2netmask(int prefix) {
+ // convert prefix to netmask
+ if (true) {
+ int mask = 0xFFFFFFFF << (32 - prefix);
+ //Log.d(TAG, "mask = " + mask + " prefix = " + prefix);
+ return ((mask>>>24) & 0xff) + "." + ((mask>>>16) & 0xff) + "." + ((mask>>>8) & 0xff) + "." + ((mask) & 0xff);
+ } else {
+ return NetworkUtils.intToInetAddress(NetworkUtils.prefixLengthToNetmaskInt(prefix)).getHostName();
+ }
+ }
+ private String getLinkGateway(LinkProperties mLinkProperties) {
+ for (RouteInfo route : mLinkProperties.getRoutes()) {
+ if (route.hasGateway()) {
+ InetAddress gateway = route.getGateway();
+ if (route.isIPv4Default()) {
+ return gateway.getHostAddress();
+ }
+ }
+ }
+ return "";
+ }
+ private String getLinkDns(LinkProperties mLinkProperties) {
+ String dns = "";
+ for (InetAddress nameserver : mLinkProperties.getDnsServers()) {
+ dns += nameserver.getHostAddress();
+ }
+ return dns;
+ }