diff options
author | markchien <markchien@google.com> | 2019-11-26 21:09:39 +0800 |
---|---|---|
committer | markchien <markchien@google.com> | 2020-01-08 17:37:21 +0800 |
commit | f52fa0ea16c0e2bfdc673dbadb58fdacedf7d4ec (patch) | |
tree | ae87a56ae15846c9a2d5a39fb525df0276615bdd | |
parent | c1eaeb31b18acf7342520398c7e3f351dea9c277 (diff) |
[Tether09] Add RouteUtils and NetdUtils
Add RouteUtils and NetdUtils file to NetworkStack module shared
folder. And it would statically linked into framework and
tethering module.
Bug: 136040414
Test: -build, flash, boot
-atest TetheringTest
Change-Id: I8c2781597b410d12407ddb743f1621bf92d2a852
-rw-r--r-- | common/moduleutils/Android.bp | 15 | ||||
-rw-r--r-- | common/moduleutils/src/android/net/ip/InterfaceController.java | 38 | ||||
-rw-r--r-- | common/moduleutils/src/android/net/shared/NetdUtils.java | 65 | ||||
-rw-r--r-- | common/moduleutils/src/android/net/shared/RouteUtils.java | 115 |
4 files changed, 222 insertions, 11 deletions
diff --git a/common/moduleutils/Android.bp b/common/moduleutils/Android.bp index 6117149..afd82e5 100644 --- a/common/moduleutils/Android.bp +++ b/common/moduleutils/Android.bp @@ -18,4 +18,17 @@ filegroup { name: "net-module-utils-srcs", srcs: ["src/**/*.java"], -}
\ No newline at end of file +} + +// Shared utility sources to be used by tethering modules +filegroup { + name: "tethering-module-utils-srcs", + srcs: [ + "src/android/net/ip/InterfaceController.java", + "src/android/net/netlink/*.java", + "src/android/net/shared/NetdUtils.java", + "src/android/net/shared/RouteUtils.java", + "src/android/net/util/InterfaceParams.java", + "src/android/net/util/SharedLog.java" + ], +} diff --git a/common/moduleutils/src/android/net/ip/InterfaceController.java b/common/moduleutils/src/android/net/ip/InterfaceController.java index f32d143..e8fc72c 100644 --- a/common/moduleutils/src/android/net/ip/InterfaceController.java +++ b/common/moduleutils/src/android/net/ip/InterfaceController.java @@ -16,6 +16,9 @@ package android.net.ip; +import static android.net.INetd.IF_STATE_DOWN; +import static android.net.INetd.IF_STATE_UP; + import android.net.INetd; import android.net.InterfaceConfigurationParcel; import android.net.LinkAddress; @@ -48,13 +51,31 @@ public class InterfaceController { mLog = log; } - private boolean setInterfaceAddress(LinkAddress addr) { + /** + * Set the IPv4 address and also optionally bring the interface up or down. + */ + public boolean setInterfaceConfiguration(final LinkAddress ipv4Addr, + final Boolean setIfaceUp) { + if (!(ipv4Addr.getAddress() instanceof Inet4Address)) { + throw new IllegalArgumentException("Invalid or mismatched Inet4Address"); + } + // Note: currently netd only support INetd#IF_STATE_UP and #IF_STATE_DOWN. + // Other flags would be ignored. + final InterfaceConfigurationParcel ifConfig = new InterfaceConfigurationParcel(); ifConfig.ifName = mIfName; - ifConfig.ipv4Addr = addr.getAddress().getHostAddress(); - ifConfig.prefixLength = addr.getPrefixLength(); + ifConfig.ipv4Addr = ipv4Addr.getAddress().getHostAddress(); + ifConfig.prefixLength = ipv4Addr.getPrefixLength(); + // Netd ignores hwaddr in interfaceSetCfg. ifConfig.hwAddr = ""; - ifConfig.flags = new String[0]; + if (setIfaceUp == null) { + // Empty array means no change. + ifConfig.flags = new String[0]; + } else { + // Netd ignores any flag that's not IF_STATE_UP or IF_STATE_DOWN in interfaceSetCfg. + ifConfig.flags = setIfaceUp.booleanValue() + ? new String[] {IF_STATE_UP} : new String[] {IF_STATE_DOWN}; + } try { mNetd.interfaceSetCfg(ifConfig); } catch (RemoteException | ServiceSpecificException e) { @@ -68,18 +89,15 @@ public class InterfaceController { /** * Set the IPv4 address of the interface. */ - public boolean setIPv4Address(LinkAddress address) { - if (!(address.getAddress() instanceof Inet4Address)) { - return false; - } - return setInterfaceAddress(address); + public boolean setIPv4Address(final LinkAddress address) { + return setInterfaceConfiguration(address, null); } /** * Clear the IPv4Address of the interface. */ public boolean clearIPv4Address() { - return setInterfaceAddress(new LinkAddress("0.0.0.0/0")); + return setIPv4Address(new LinkAddress("0.0.0.0/0")); } private boolean setEnableIPv6(boolean enabled) { diff --git a/common/moduleutils/src/android/net/shared/NetdUtils.java b/common/moduleutils/src/android/net/shared/NetdUtils.java new file mode 100644 index 0000000..0137bb7 --- /dev/null +++ b/common/moduleutils/src/android/net/shared/NetdUtils.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.shared; + +import static android.net.RouteInfo.RTN_UNICAST; + +import android.net.INetd; +import android.net.IpPrefix; +import android.net.RouteInfo; +import android.net.TetherConfigParcel; +import android.os.RemoteException; +import android.os.ServiceSpecificException; + +import java.util.ArrayList; +import java.util.List; + +/** + * Implements common operations on INetd + * @hide + */ +public class NetdUtils { + /** Start tethering. */ + public static void tetherStart(final INetd netd, final boolean usingLegacyDnsProxy, + final String[] dhcpRange) throws RemoteException, ServiceSpecificException { + final TetherConfigParcel config = new TetherConfigParcel(); + config.usingLegacyDnsProxy = usingLegacyDnsProxy; + config.dhcpRanges = dhcpRange; + netd.tetherStartWithConfiguration(config); + } + + /** Setup interface for tethering. */ + public static void tetherInterface(final INetd netd, final String iface, final IpPrefix dest) + throws RemoteException, ServiceSpecificException { + netd.tetherInterfaceAdd(iface); + + netd.networkAddInterface(INetd.LOCAL_NET_ID, iface); + List<RouteInfo> routes = new ArrayList<>(); + routes.add(new RouteInfo(dest, null, iface, RTN_UNICAST)); + RouteUtils.addRoutesToLocalNetwork(netd, iface, routes); + } + + /** Reset interface for tethering. */ + public static void untetherInterface(final INetd netd, String iface) + throws RemoteException, ServiceSpecificException { + try { + netd.tetherInterfaceRemove(iface); + } finally { + netd.networkRemoveInterface(INetd.LOCAL_NET_ID, iface); + } + } +} diff --git a/common/moduleutils/src/android/net/shared/RouteUtils.java b/common/moduleutils/src/android/net/shared/RouteUtils.java new file mode 100644 index 0000000..54ff675 --- /dev/null +++ b/common/moduleutils/src/android/net/shared/RouteUtils.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.net.shared; + +import static android.net.RouteInfo.RTN_THROW; +import static android.net.RouteInfo.RTN_UNICAST; +import static android.net.RouteInfo.RTN_UNREACHABLE; + +import android.net.INetd; +import android.net.IpPrefix; +import android.net.RouteInfo; +import android.os.RemoteException; +import android.os.ServiceSpecificException; + +import java.util.List; + +/** @hide*/ +public class RouteUtils { + + /** Used to modify the specified route. */ + public enum ModifyOperation { + ADD, + REMOVE, + } + + private static String findNextHop(final RouteInfo route) { + final String nextHop; + switch (route.getType()) { + case RTN_UNICAST: + if (route.hasGateway()) { + nextHop = route.getGateway().getHostAddress(); + } else { + nextHop = INetd.NEXTHOP_NONE; + } + break; + case RTN_UNREACHABLE: + nextHop = INetd.NEXTHOP_UNREACHABLE; + break; + case RTN_THROW: + nextHop = INetd.NEXTHOP_THROW; + break; + default: + nextHop = INetd.NEXTHOP_NONE; + break; + } + return nextHop; + } + + /** Add |routes| to local network. */ + public static void addRoutesToLocalNetwork(final INetd netd, final String iface, + final List<RouteInfo> routes) { + + for (RouteInfo route : routes) { + if (!route.isDefaultRoute()) { + modifyRoute(netd, ModifyOperation.ADD, INetd.LOCAL_NET_ID, route); + } + } + + // IPv6 link local should be activated always. + modifyRoute(netd, ModifyOperation.ADD, INetd.LOCAL_NET_ID, + new RouteInfo(new IpPrefix("fe80::/64"), null, iface, RTN_UNICAST)); + } + + /** Remove routes from local network. */ + public static int removeRoutesFromLocalNetwork(final INetd netd, final List<RouteInfo> routes) { + int failures = 0; + + for (RouteInfo route : routes) { + try { + modifyRoute(netd, ModifyOperation.REMOVE, INetd.LOCAL_NET_ID, route); + } catch (IllegalStateException e) { + failures++; + } + } + + return failures; + } + + /** Add or remove |route|. */ + public static void modifyRoute(final INetd netd, final ModifyOperation op, final int netId, + final RouteInfo route) { + final String ifName = route.getInterface(); + final String dst = route.getDestination().toString(); + final String nextHop = findNextHop(route); + + try { + switch(op) { + case ADD: + netd.networkAddRoute(netId, ifName, dst, nextHop); + break; + case REMOVE: + netd.networkRemoveRoute(netId, ifName, dst, nextHop); + break; + default: + throw new IllegalStateException("Unsupported modify operation:" + op); + } + } catch (RemoteException | ServiceSpecificException e) { + throw new IllegalStateException(e); + } + } + +} |