移动网络共享到以太网
RK3288 android 7.1
- 实现4G和以太网共存—《Android 支持双以太网卡补丁20180108》
- 再把4G信号通过iptables实现路由转发
开启双以太网共存
adb shell setprop persist.net.ethernet.mode multi
adb路由转发
- ip rule add from all lookup main pref 9999
- ifconfig eth0 down
- ifconfig eth0 up
- busybox ifconfig eth0 192.168.43.1
- ndc netd 5003 tether start 192.168.43.2 192.168.43.254
- ndc netd 7 nat enable eth0 usb0 1 10.80.71.155/24 (4G ip)
- echo 1 > /proc/sys/net/ipv4/ip_forward
- getprop grep dns
- iptables -t nat -I PREROUTING -i eth0 -p udp –dport 53 -j DNAT –to-destination 120.196.165.7(usb0 dns)
ifconfig
网络共享前
$ ifconfig
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope: Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:10 errors:0 dropped:0 overruns:0 frame:0
TX packets:10 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1
RX bytes:762 TX bytes:762
eth0 Link encap:Ethernet HWaddr 8a:5b:57:f2:44:77
inet6 addr: fe80::885b:57ff:fef2:4477/64 Scope: Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:2 errors:0 dropped:0 overruns:0 frame:0
TX packets:56 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:700 TX bytes:14176
Interrupt:42
usb0 Link encap:Ethernet HWaddr ae:0c:29:a3:9b:6d
inet addr:10.52.206.88 Bcast:10.255.255.255 Mask:255.0.0.0
inet6 addr: fe80::ac0c:29ff:fea3:9b6d/64 Scope: Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1479 errors:0 dropped:0 overruns:0 frame:0
TX packets:1718 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:123222 TX bytes:180776
网络共享后
# ifconfig
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope: Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:2 errors:0 dropped:0 overruns:0 frame:0
TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1
RX bytes:106 TX bytes:106
eth0 Link encap:Ethernet HWaddr 8a:5b:57:f2:44:77
inet addr:192.168.43.1 Bcast:192.168.43.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:735 errors:0 dropped:0 overruns:0 frame:0
TX packets:802 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:84584 TX bytes:965347
Interrupt:42
usb0 Link encap:Ethernet HWaddr ae:0c:29:a3:9b:6d
inet addr:10.129.70.7 Bcast:10.255.255.255 Mask:255.0.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1274 errors:0 dropped:0 overruns:0 frame:0
TX packets:1247 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:1390060 TX bytes:135432
app
TetherUtils
import android.content.Context;
import android.os.SystemProperties;
import android.util.Log;
import com.wif.settings.frameworks.NetworkManagement;
import com.wif.settings.reflex.EthernetReflex;
public class TetherUtils {
public static final String TAG = "TetherUtils";
public static final String DEFAULT_IP = "192.168.43.1";
public static final String DEFAULT_IP_MASK = "192.168.43.1/24";
public static final String ROUTE_ADDRESS = "10.6.194.114/24";
private static final String[] DHCP_DEFAULT_RANGE = {
// "192.168.42.2", "192.168.42.254",
"192.168.43.2", "192.168.43.254",
// "192.168.44.2", "192.168.44.254",
// "192.168.45.2", "192.168.45.254",
// "192.168.46.2", "192.168.46.254",
// "192.168.47.2", "192.168.47.254",
// "192.168.48.2", "192.168.48.254",
// "192.168.49.2", "192.168.49.254",
};
public static final String INTERFACE_ETHERNET = "eth0";
public static final String INTERFACE_4G = "usb0";
public static final String PROP_ETHERNET_MODE = "persist.net.ethernet.mode";
public static final String MULTI = "multi";
public static final String NORMAL = "normal";
public static void startTetherShare(Context context) {
Log.i(TAG, "startTetherShare");
NetworkManagement.ipRuleConfig();
NetworkManagement.ifconfig(INTERFACE_ETHERNET, "down");
threadSleep(100);
NetworkManagement.ifconfig(INTERFACE_ETHERNET, "up");
//NetworkManagement.ifconfig(INTERFACE_ETHERNET, DEFAULT_IP);
setStaticIpEth0(context);
NetworkManagement.startTethering(DHCP_DEFAULT_RANGE);
NetworkManagement.enableNatRoute(INTERFACE_ETHERNET, INTERFACE_4G, "1", DEFAULT_IP_MASK);
NetworkManagement.setIpForwardingEnabled(true);
String dns = SystemProperties.get("net.dns1");
NetworkManagement.iptablesRoute(INTERFACE_ETHERNET, dns);
}
public static void stopTetherShare() {
Log.i(TAG, "stopTetherShare");
NetworkManagement.disableNat(INTERFACE_ETHERNET, INTERFACE_4G);
NetworkManagement.stopTethering();
NetworkManagement.setIpForwardingEnabled(false);
NetworkManagement.ifconfig(INTERFACE_ETHERNET, "down");
threadSleep(100);
NetworkManagement.ifconfig(INTERFACE_ETHERNET, "up");
}
public static void setStaticIpEth0(Context context) {
String dns1 = SystemProperties.get("net.usb0.dns1");
String dns2 = SystemProperties.get("net.usb0.dns2");
EthernetReflex.setEthernetStaticIp(context, DEFAULT_IP,
"255.255.255.0", "192.168.1.1", dns1, dns2);
}
public static void threadSleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
NetworkManagement
import android.annotation.SuppressLint;
import android.net.LinkAddress;
import android.os.INetworkManagementService;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
public class NetworkManagement {
public static final String TAG = "NetworkManagement";
private static final String NETWORK_MANAGEMENT_SERVICE = "network_management";
public static INetworkManagementService sNMS = getNMS();
public static INetworkManagementService getNMS() {
if (sNMS != null) {
return sNMS;
}
return INetworkManagementService.Stub.asInterface(ServiceManager.getService(NETWORK_MANAGEMENT_SERVICE));
}
public static void ipRuleConfig() {
final INetworkManagementService netManager = getNMS();
if (netManager == null) {
Log.e(TAG, "netManager is null");
return;
}
try {
netManager.ipRuleConfig();
} catch (RemoteException | NoSuchMethodError | IllegalStateException e) {
e.printStackTrace();
}
}
public static void ifconfig(String iface, String args) {
final INetworkManagementService netManager = getNMS();
if (netManager == null) {
Log.e(TAG, "netManager is null");
return;
}
try {
netManager.ifconfig(iface, args);
} catch (RemoteException | NoSuchMethodError | IllegalStateException e) {
e.printStackTrace();
}
}
public static void setInterfaceDown(String iface) {
final INetworkManagementService netManager = getNMS();
if (netManager == null) {
Log.e(TAG, "netManager is null");
return;
}
try {
netManager.setInterfaceDown(iface);
} catch (RemoteException | NoSuchMethodError | IllegalStateException e) {
e.printStackTrace();
}
}
public static void setInterfaceUp(String iface) {
final INetworkManagementService netManager = getNMS();
if (netManager == null) {
Log.e(TAG, "netManager is null");
return;
}
try {
netManager.setInterfaceUp(iface);
} catch (RemoteException | NoSuchMethodError | IllegalStateException e) {
e.printStackTrace();
}
}
public static boolean isTetheringStarted() {
final INetworkManagementService netManager = getNMS();
if (netManager == null) {
Log.e(TAG, "netManager is null");
return false;
}
try {
return netManager.isTetheringStarted();
} catch (RemoteException | NoSuchMethodError | IllegalStateException e) {
e.printStackTrace();
}
return false;
}
public static void startTethering(String[] dhcpRange) {
final INetworkManagementService netManager = getNMS();
if (netManager == null) {
Log.e(TAG, "netManager is null");
return;
}
try {
netManager.startTethering(dhcpRange);
} catch (RemoteException | NoSuchMethodError | IllegalStateException e) {
e.printStackTrace();
}
}
public static void stopTethering() {
final INetworkManagementService netManager = getNMS();
if (netManager == null) {
Log.e(TAG, "netManager is null");
return;
}
try {
netManager.stopTethering();
} catch (RemoteException | NoSuchMethodError | IllegalStateException e) {
e.printStackTrace();
}
}
public static void enableNat(String internalInterface, String externalInterface) {
final INetworkManagementService netManager = getNMS();
if (netManager == null) {
Log.e(TAG, "netManager is null");
return;
}
try {
netManager.enableNat(internalInterface, externalInterface);
} catch (RemoteException | NoSuchMethodError | IllegalStateException e) {
e.printStackTrace();
}
}
public static void enableNatRoute(String internalInterface, String externalInterface, String addressSize, String address) {
final INetworkManagementService netManager = getNMS();
if (netManager == null) {
Log.e(TAG, "netManager is null");
return;
}
try {
netManager.enableNatRoute(internalInterface, externalInterface, addressSize, address);
} catch (RemoteException | NoSuchMethodError | IllegalStateException e) {
e.printStackTrace();
}
}
public static void disableNat(String internalInterface, String externalInterface) {
final INetworkManagementService netManager = getNMS();
if (netManager == null) {
Log.e(TAG, "netManager is null");
return;
}
try {
netManager.disableNat(internalInterface, externalInterface);
} catch (RemoteException | NoSuchMethodError | IllegalStateException e) {
e.printStackTrace();
}
}
public static void setIpForwardingEnabled(boolean enabled) {
final INetworkManagementService netManager = getNMS();
if (netManager == null) {
Log.e(TAG, "netManager is null");
return;
}
try {
netManager.setIpForwardingEnabled(enabled);
} catch (RemoteException | NoSuchMethodError | IllegalStateException e) {
e.printStackTrace();
}
}
public static void iptablesRoute(String iface, String dns) {
final INetworkManagementService netManager = getNMS();
if (netManager == null) {
Log.e(TAG, "netManager is null");
return;
}
try {
netManager.iptablesRoute(iface, dns);
} catch (RemoteException | NoSuchMethodError | IllegalStateException e) {
e.printStackTrace();
}
}
public static LinkAddress getInterfaceAddress(String iface){
final INetworkManagementService netManager = getNMS();
if (netManager == null) {
Log.e(TAG, "netManager is null");
return null;
}
try {
return netManager.getInterfaceAddress(iface);
} catch (RemoteException | NoSuchMethodError | IllegalStateException e) {
e.printStackTrace();
}
return null;
}
@SuppressLint("NewApi")
public static String getInterfaceIpAddress(String iface){
LinkAddress linkAddress = getInterfaceAddress(iface);
if (linkAddress == null) {
return null;
}
if (linkAddress.getAddress() == null) {
return null;
}
return linkAddress.getAddress().getHostAddress();
}
}
system_server
NetworkManagementService
public class NetworkManagementService extends INetworkManagementService.Stub
implements Watchdog.Monitor {
@Override
public void ipRuleConfig() {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Slog.d(TAG, "ipRuleConfig");
try {
mConnector.execute("tether", "ip_rule");
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
}
@Override
public void ifconfig(String iface, String args) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Slog.d(TAG, "ifconfig " + iface + " " + args);
try {
mConnector.execute("tether", "ifconfig", iface, args);
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
}
@Override
public void enableNatRoute(String internalInterface, String externalInterface, String addressSize, String address) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Slog.d(TAG, "enableNatRoute " + internalInterface + " " + externalInterface + " " + address);
final Command cmd = new Command("nat", "enable", internalInterface, externalInterface);
try {
final NetworkInterface internalNetworkInterface = NetworkInterface.getByName(
internalInterface);
if (internalNetworkInterface == null) {
cmd.appendArg("0");
} else {
cmd.appendArg(addressSize);
cmd.appendArg(address);
}
mConnector.execute(cmd);
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
} catch (SocketException e) {
throw new IllegalStateException(e);
}
}
@Override
public void iptablesRoute(String iface, String dns) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Slog.d(TAG, "iptablesRoute " + iface + " " + dns);
try {
mConnector.execute("tether", "iptables_route", iface, dns);
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
}
public LinkAddress getInterfaceAddress(String iface) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
//Slog.d(TAG, "getInterfaceAddress: " + iface);
final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
if (ifcg == null) {
return null;
}
return ifcg.getLinkAddress();
}
}
netd
CommandListener.cpp
int CommandListener::TetherCmd::runCommand(SocketClient *cli,
int argc, char **argv) {
else if (!strcmp(argv[1], "ip_rule")) {
gCtls->tetherCtrl.ipRuleConfig();
} else if (!strcmp(argv[1], "ifconfig")) {
gCtls->tetherCtrl.ifconfig(argv[2], argv[3]);
} else if (!strcmp(argv[1], "iptables_route")) {
gCtls->tetherCtrl.iptablesRoute(argv[2], argv[3]);
}
}
TetherController.cpp
int TetherController::ipRuleConfig() {
ALOGW("runCommand: ip rule add from all lookup main pref 9999");
for (size_t i = 0; i < ARRAY_SIZE(IP_VERSIONS); ++i) {
const char* argv[] = {
IP_PATH,
IP_VERSIONS[i],
"rule",
"add",
"from",
"all",
"lookup",
"main",
"pref",
"9999",
};
if (android_fork_execvp(ARRAY_SIZE(argv), const_cast<char**>(argv), NULL, false, false)) {
ALOGE("ip rule add from all lookup main pref 9999------fail");
return -EREMOTEIO;
}
}
return 0;
}
int TetherController::ifconfig(const char* interface, const char* args) {
ALOGW("runCommand: ifconfig %s %s", interface, args);
if (!isIfaceName(interface)) {
errno = ENOENT;
return -1;
}
const char* argv[] = {
"/system/bin/ifconfig",
interface,
args,
};
if (android_fork_execvp(ARRAY_SIZE(argv), const_cast<char**>(argv), NULL, false, false)) {
ALOGE("ifconfig %s %s------fail", interface, args);
return -EREMOTEIO;
}
return 0;
}
int TetherController::iptablesRoute(const char* interface, const char* dns) {
ALOGW("runCommand: iptablesRoute %s %s", interface, dns);
if (!isIfaceName(interface)) {
errno = ENOENT;
return -1;
}
const char* argv[] = {
IPTABLES_PATH,
"-t",
"nat",
"-I",
"PREROUTING",
"-i",
interface,
"-p",
"udp",
"--dport",
"53",
"-j",
"DNAT",
"--to-destination",
dns
};
if (android_fork_execvp(ARRAY_SIZE(argv), const_cast<char**>(argv), NULL, false, false)) {
ALOGE("iptables -t nat -I PREROUTING -i %s -p udp --dport 53 -j DNAT --to-destination %s", interface, dns);
return -EREMOTEIO;
}
return 0;
}